* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame @ 2012-10-07 23:03 Christoph Scholtes 2012-10-08 7:31 ` Eli Zaretskii 2012-10-15 9:40 ` martin rudalics 0 siblings, 2 replies; 34+ messages in thread From: Christoph Scholtes @ 2012-10-07 23:03 UTC (permalink / raw) To: 12600 emacs -Q Load large file, e.g. emacs.c. Buffer content must exceed one screen. Enable linum mode with `M-x linum-mode'. Shrink frame. Maximize frame. Fringe on the left side is missing line numbers. Move cursor down with `C-n' and the fringe refreshes and displays all line numbers. In GNU Emacs 24.2.50.1 (x86_64-unknown-linux-gnu, GTK+ Version 2.24.10) of 2012-10-07 on marvin Bzr revision: 110431 fabian@anue.biz-20121007193737-y7fsm9ts74jks2so Windowing system distributor `The X.Org Foundation', version 11.0.11103000 System Description: Ubuntu 12.04.1 LTS Configured using: `configure 'CC=clang'' Important settings: value of $LANG: en_US.UTF-8 locale-coding-system: utf-8-unix default enable-multibyte-characters: t Major mode: C/l Minor modes in effect: linum-mode: t tooltip-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 Recent input: M-x C-g C-x C-f e m c a s . <backspace> <backspace> <backspace> <backspace> a c s . c <return> M-x l i n u m <tab> <return> C-n C-p M-x r e p o r t <tab> <return> Recent messages: For information about GNU Emacs and the GNU system, type C-h C-a. Quit emacs.c has auto save data; consider M-x recover-this-file Loading cc-langs...done Loading vc-bzr...done Linum mode enabled Load-path shadows: None found. Features: (shadow sort gnus-util mail-extr emacsbug message cl-macs gv format-spec rfc822 mml mml-sec mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils linum vc-bzr cc-langs cl cl-lib cc-mode cc-fonts easymenu cc-guess cc-menus cc-cmds cc-styles cc-align cc-engine cc-vars cc-defs time-date tooltip ediff-hook vc-hooks lisp-float-type mwheel x-win x-dnd tool-bar dnd fontset image regexp-opt fringe tabulated-list newcomment lisp-mode register page menu-bar rfn-eshadow timer select scroll-bar mouse jit-lock font-lock syntax facemenu font-core frame cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese case-table epa-hook jka-cmpr-hook help simple abbrev minibuffer loaddefs button faces cus-face macroexp files text-properties overlay sha1 md5 base64 format env code-pages mule custom widget hashtable-print-readable backquote make-network-process dbusbind dynamic-setting system-font-setting font-render-setting move-toolbar gtk x-toolkit x multi-tty emacs) ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-07 23:03 bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame Christoph Scholtes @ 2012-10-08 7:31 ` Eli Zaretskii 2012-10-08 9:17 ` martin rudalics 2012-10-15 9:40 ` martin rudalics 1 sibling, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-08 7:31 UTC (permalink / raw) To: Christoph Scholtes; +Cc: 12600 > Date: Sun, 07 Oct 2012 17:03:43 -0600 > From: Christoph Scholtes <cschol2112@gmail.com> > > emacs -Q > > Load large file, e.g. emacs.c. Buffer content must exceed one > screen. > > Enable linum mode with `M-x linum-mode'. > > Shrink frame. Maximize frame. Fringe on the left side is missing line > numbers. What do you mean by "shrink" and "maximize", exactly? Clicking on the maximize button on the upper left corner of the Emacs frame (on MS-Windows) doesn't reproduce the problem. ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-08 7:31 ` Eli Zaretskii @ 2012-10-08 9:17 ` martin rudalics 2012-10-08 13:59 ` Stefan Monnier 2012-10-08 15:48 ` Eli Zaretskii 0 siblings, 2 replies; 34+ messages in thread From: martin rudalics @ 2012-10-08 9:17 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 >> emacs -Q >> >> Load large file, e.g. emacs.c. Buffer content must exceed one >> screen. >> >> Enable linum mode with `M-x linum-mode'. >> >> Shrink frame. Maximize frame. Fringe on the left side is missing line >> numbers. > > What do you mean by "shrink" and "maximize", exactly? Clicking on the > maximize button on the upper left corner of the Emacs frame (on > MS-Windows) doesn't reproduce the problem. It does so here. For whatever reason the position reported by `window-end' in `linum-update-window' is still the same as before the maximize. Moving the cursor by one character makes the numbers appear. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-08 9:17 ` martin rudalics @ 2012-10-08 13:59 ` Stefan Monnier 2012-10-08 15:48 ` Eli Zaretskii 1 sibling, 0 replies; 34+ messages in thread From: Stefan Monnier @ 2012-10-08 13:59 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > It does so here. For whatever reason the position reported by > `window-end' in `linum-update-window' is still the same as before the > maximize. Moving the cursor by one character makes the numbers appear. I'd expect that the problem does not affect nlinum.el. Stefan ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-08 9:17 ` martin rudalics 2012-10-08 13:59 ` Stefan Monnier @ 2012-10-08 15:48 ` Eli Zaretskii 2012-10-09 9:36 ` martin rudalics 1 sibling, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-08 15:48 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Mon, 08 Oct 2012 11:17:44 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: Christoph Scholtes <cschol2112@gmail.com>, 12600@debbugs.gnu.org > > >> emacs -Q > >> > >> Load large file, e.g. emacs.c. Buffer content must exceed one > >> screen. > >> > >> Enable linum mode with `M-x linum-mode'. > >> > >> Shrink frame. Maximize frame. Fringe on the left side is missing line > >> numbers. > > > > What do you mean by "shrink" and "maximize", exactly? Clicking on the > > maximize button on the upper left corner of the Emacs frame (on > > MS-Windows) doesn't reproduce the problem. > > It does so here. For whatever reason the position reported by > `window-end' in `linum-update-window' is still the same as before the > maximize. Moving the cursor by one character makes the numbers appear. I don't think we can trust redisplay to have updated the screen before the hooks used by linum-mode run. ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-08 15:48 ` Eli Zaretskii @ 2012-10-09 9:36 ` martin rudalics 2012-10-09 17:04 ` Eli Zaretskii 0 siblings, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-09 9:36 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 > I don't think we can trust redisplay to have updated the screen before > the hooks used by linum-mode run. So what does If UPDATE is non-nil, compute the up-to-date position if it isn't already recorded. in the doc-string of `window-end' really stand for? martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-09 9:36 ` martin rudalics @ 2012-10-09 17:04 ` Eli Zaretskii 2012-10-10 10:22 ` martin rudalics 0 siblings, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-09 17:04 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Tue, 09 Oct 2012 11:36:41 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: cschol2112@gmail.com, 12600@debbugs.gnu.org > > > I don't think we can trust redisplay to have updated the screen before > > the hooks used by linum-mode run. > > So what does > > If UPDATE is non-nil, compute the up-to-date position > if it isn't already recorded. > > in the doc-string of `window-end' really stand for? That it does whatever it can to retrieve the information. But if the info is not there, e.g., if the resize didn't yet cause the glyph matrices to be reallocated to match the new size, we cannot expect redisplay to succeed in this case. When you reproduce the problem, do you see the code conditioned by the 'if' shown below being executed at all? (Btw, it looks like linum-mode doesn't expect to get nil from window-end, although the doc string explicitly says it's possible.) if (! NILP (update) && ! (! NILP (w->window_end_valid) && w->last_modified >= BUF_MODIFF (b) && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)) && !noninteractive) ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-09 17:04 ` Eli Zaretskii @ 2012-10-10 10:22 ` martin rudalics 2012-10-10 15:45 ` Eli Zaretskii 0 siblings, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-10 10:22 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 > When you reproduce the problem, do you see the code conditioned by the > 'if' shown below being executed at all? No. > (Btw, it looks like linum-mode doesn't expect to get nil from > window-end, although the doc string explicitly says it's possible.) I suppose the doc-string is wrong since otherwise we should have seen this already reported. IIUC it returns either value = make_number (IT_CHARPOS (it)); or XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos)); while the nil reporting part was disabled. > > if (! NILP (update) > && ! (! NILP (w->window_end_valid) > && w->last_modified >= BUF_MODIFF (b) > && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)) > && !noninteractive) Is there anything that has not been set when the frame got resized? martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-10 10:22 ` martin rudalics @ 2012-10-10 15:45 ` Eli Zaretskii 2012-10-11 7:12 ` martin rudalics 0 siblings, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-10 15:45 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Wed, 10 Oct 2012 12:22:56 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: cschol2112@gmail.com, 12600@debbugs.gnu.org > > > When you reproduce the problem, do you see the code conditioned by the > > 'if' shown below being executed at all? > > No. QED. Redisplay thinks that nothing's changed, and returns the previous (wrong) window-end. > > (Btw, it looks like linum-mode doesn't expect to get nil from > > window-end, although the doc string explicitly says it's possible.) > > I suppose the doc-string is wrong since otherwise we should have seen > this already reported. IIUC it returns either > > value = make_number (IT_CHARPOS (it)); > > or > > XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos)); > > while the nil reporting part was disabled. It was disabled with a comment saying #if 0 /* This change broke some things. We should make it later. */ ^^^^^^^^^^^^^^^^^^^^^^^ If everybody agrees that the doc string is wrong, then we should permanently delete this code when we update the doc. Otherwise, some day the function will begin returning nil, and applications should be prepared for that. > > if (! NILP (update) > > && ! (! NILP (w->window_end_valid) > > && w->last_modified >= BUF_MODIFF (b) > > && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)) > > && !noninteractive) > > Is there anything that has not been set when the frame got resized? I'm guessing it's the window_end_valid flag, since no buffer changes are involved in the recipe. Which probably means that the resize did not yet become known to the display engine by the time this function is called. Of course, this is all theory, and I was wrong before. It would be best to trace this with a debugger and see what's going on. ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-10 15:45 ` Eli Zaretskii @ 2012-10-11 7:12 ` martin rudalics 2012-10-11 16:56 ` Eli Zaretskii 0 siblings, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-11 7:12 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 > It was disabled with a comment saying > > #if 0 /* This change broke some things. We should make it later. */ > ^^^^^^^^^^^^^^^^^^^^^^^ > If everybody agrees that the doc string is wrong, then we should > permanently delete this code when we update the doc. Otherwise, some > day the function will begin returning nil, and applications should be > prepared for that. Looking at the ChangeLogs this apparently changed back and forth two times with limited success. >> > if (! NILP (update) >> > && ! (! NILP (w->window_end_valid) >> > && w->last_modified >= BUF_MODIFF (b) >> > && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)) >> > && !noninteractive) >> >> Is there anything that has not been set when the frame got resized? > > I'm guessing it's the window_end_valid flag, since no buffer changes > are involved in the recipe. Which probably means that the resize did > not yet become known to the display engine by the time this function > is called. > > Of course, this is all theory, and I was wrong before. It would be > best to trace this with a debugger and see what's going on. I have no idea what these window structure members (window_end_valid, last_modified and last_overlay_modified) stand for in practice, who's supposed to set them, why and when. At least setting window_end_valid to Qnil in window_resize_apply did not help. But writing if (! NILP (update) /** && ! (! NILP (w->window_end_valid) **/ /** && w->last_modified >= BUF_MODIFF (b) **/ /** && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)) **/ && !noninteractive) makes the problem disappear. So apparently this can be fixed easily but as long as I don't understand that cryptic conjunct I won't do it. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-11 7:12 ` martin rudalics @ 2012-10-11 16:56 ` Eli Zaretskii 2012-10-12 7:32 ` martin rudalics 0 siblings, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-11 16:56 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Thu, 11 Oct 2012 09:12:50 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: cschol2112@gmail.com, 12600@debbugs.gnu.org > > I have no idea what these window structure members (window_end_valid, > last_modified and last_overlay_modified) stand for in practice, who's > supposed to set them, why and when. At least setting window_end_valid > to Qnil in window_resize_apply did not help. But writing > > if (! NILP (update) > /** && ! (! NILP (w->window_end_valid) **/ > /** && w->last_modified >= BUF_MODIFF (b) **/ > /** && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)) **/ > && !noninteractive) > > makes the problem disappear. > > So apparently this can be fixed easily but as long as I don't understand > that cryptic conjunct I won't do it. That 'if' is just an optimization: it tries to avoid a (potentially expensive) call to move_it_vertically. It could be expensive with large windows and/or very long lines, for example. So if window-end is not supposed to be called in some inner loop, and we don't mind getting slower on behalf of a package whose design is known to be flawed anyway, we can disable the optimization. Disabling this optimization should never do any harm, AFAIU, except slow down the function. ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-11 16:56 ` Eli Zaretskii @ 2012-10-12 7:32 ` martin rudalics 2012-10-12 8:52 ` Eli Zaretskii 0 siblings, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-12 7:32 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 >> if (! NILP (update) >> /** && ! (! NILP (w->window_end_valid) **/ >> /** && w->last_modified >= BUF_MODIFF (b) **/ >> /** && w->last_overlay_modified >= BUF_OVERLAY_MODIFF (b)) **/ >> && !noninteractive) >> >> makes the problem disappear. >> >> So apparently this can be fixed easily but as long as I don't understand >> that cryptic conjunct I won't do it. > > That 'if' is just an optimization: it tries to avoid a (potentially > expensive) call to move_it_vertically. It could be expensive with > large windows and/or very long lines, for example. > > So if window-end is not supposed to be called in some inner loop, and > we don't mind getting slower on behalf of a package whose design is > known to be flawed anyway, we can disable the optimization. Disabling > this optimization should never do any harm, AFAIU, except slow down > the function. Before doing that, could you please in window.h eventually update the comments for display related fields like last_modified, last_overlay_modified, last_point to say who's supposed to (re-)set them to which value. I'm afraid the current situation is a mess. For example, what does the "displayed buffer's text modification events counter as of last time display completed" mean? Suppose redisplay has set this to 37. Apparently, setting it to 36 means that the next redisplay will notice that for this window display is not accurate and has to be redone because 36 < 37. But why is a flag insufficient to accomplish that? IIUC it's set only once by mark_window_display_accurate_1 and everywhere else reset to 0. Why can't we set it to "accurate" in mark_window_display_accurate_1 and "inaccurate" everwhere else? And why do we have additional fields for last_overlay_modified and window_end_valid? What sense does it make to handle these separately? For example, wherever last_modified is reset to 0 last_overlay_modified is always reset to 0 too. Isn't that plain overkill? martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-12 7:32 ` martin rudalics @ 2012-10-12 8:52 ` Eli Zaretskii 2012-10-12 9:35 ` martin rudalics 0 siblings, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-12 8:52 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Fri, 12 Oct 2012 09:32:01 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: cschol2112@gmail.com, 12600@debbugs.gnu.org > > Before doing that, could you please in window.h eventually update the > comments for display related fields like last_modified, > last_overlay_modified, last_point to say who's supposed to (re-)set them > to which value. I would like to, but I need some guidance as to what is unclear, see below. > I'm afraid the current situation is a mess. I can agree to that. Quite a few struct members related to the display engine (and I suppose other core structures as well) are insufficiently, in accurately, or even downright incorrectly documented. I try to fix every such problem I bump into, FWIW. > For example, what does the "displayed buffer's text modification events > counter as of last time display completed" mean? This one sounds quite clear, please tell which part needs further clarifications. It would be better to say "counter of the displayed buffer's modification events as of last time display completed", but somehow I'm guessing it's not what you had in mind. > Suppose redisplay has set this to 37. Apparently, setting it to 36 > means that the next redisplay will notice that for this window > display is not accurate and has to be redone because 36 < 37. Not necessarily. It depends on what is recorded in the buffer's BUF_MODIFF slot. > But why is a flag insufficient to accomplish that? IIUC it's set only > once by mark_window_display_accurate_1 and everywhere else reset to 0. > Why can't we set it to "accurate" in mark_window_display_accurate_1 and > "inaccurate" everwhere else? How would this work when the displayed buffer is modified behind redisplay's back? The last_modified slot belongs to the window, which redisplay controls, but it doesn't control the buffer, which could well be displayed in other windows as well and modified through there. The display engine treats each window separately; when it displays some window, it doesn't use information from other windows. > And why do we have additional fields for last_overlay_modified and > window_end_valid? What sense does it make to handle these separately? Because changes in overlays do not constitute changes in buffer contents, and are done via yet another set of primitives, yet they do require redisplay. Also because each one of these can allow and disallow certain distinct redisplay optimizations, at least in principle. As for window_end_valid flag, it's there to allow yet another set of redisplay optimizations. > For example, wherever last_modified is reset to 0 last_overlay_modified > is always reset to 0 too. Isn't that plain overkill? The potential for separate optimizations is not realized, that's true. But it exists; I'm not sure we should remove it, and I surely won't spend any of my personal time trying. Fixing real bugs in the display engine is enough to fill my free time already. Of course, if you feel like it, and if no one objects, feel free to make these cleanups. ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-12 8:52 ` Eli Zaretskii @ 2012-10-12 9:35 ` martin rudalics 2012-10-12 13:51 ` Eli Zaretskii 2012-10-12 14:55 ` Stefan Monnier 0 siblings, 2 replies; 34+ messages in thread From: martin rudalics @ 2012-10-12 9:35 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 > Quite a few struct members related to the > display engine (and I suppose other core structures as well) are > insufficiently, in accurately, or even downright incorrectly > documented. I try to fix every such problem I bump into, FWIW. If these concern the display engine exclusively, there's no problem. Problems arise when the window handling code is supposed to change them. >> For example, what does the "displayed buffer's text modification events >> counter as of last time display completed" mean? > > This one sounds quite clear, please tell which part needs further > clarifications. It would be better to say "counter of the displayed > buffer's modification events as of last time display completed", but > somehow I'm guessing it's not what you had in mind. That's exactly what I had in mind: Either something that corresponds textually to what is used in buffer.h or just mention the name of the corresponding field used in buffer.h. As it stands currently, I have to either guess what is meant or go through the comparisons in the code to find out. >> Suppose redisplay has set this to 37. Apparently, setting it to 36 >> means that the next redisplay will notice that for this window >> display is not accurate and has to be redone because 36 < 37. > > Not necessarily. It depends on what is recorded in the buffer's > BUF_MODIFF slot. IIUC this can only increase monotonously (modulo wraparounds, but in that case ...). >> But why is a flag insufficient to accomplish that? IIUC it's set only >> once by mark_window_display_accurate_1 and everywhere else reset to 0. >> Why can't we set it to "accurate" in mark_window_display_accurate_1 and >> "inaccurate" everwhere else? > > How would this work when the displayed buffer is modified behind > redisplay's back? The last_modified slot belongs to the window, which > redisplay controls, but it doesn't control the buffer, which could > well be displayed in other windows as well and modified through there. > The display engine treats each window separately; when it displays > some window, it doesn't use information from other windows. When last_modifed_flag is set, the window must be redisplayed. Now if someone else (including the display engine) decremented last_modified, things were different indeed. But as it stands I don't see any such assignment. OTOH when the buffer iself is modified it has to be redisplayed anyway because we hardly know where the change happened. So I don't see why such a comparison of counters is useful. But maybe I'm missing something. >> And why do we have additional fields for last_overlay_modified and >> window_end_valid? What sense does it make to handle these separately? > > Because changes in overlays do not constitute changes in buffer > contents, and are done via yet another set of primitives, yet they do > require redisplay. Also because each one of these can allow and > disallow certain distinct redisplay optimizations, at least in > principle. I doubt whether such optimizations exist. Suppose we could exclude a change to happen within the bounds of a window as for example a buffer displayed with a window starting at M and ending at N and an overlay modified at some position < M or > N. Wouldn't this require to associate each single overlay with a modification counter? > As for window_end_valid flag, it's there to allow yet another set of > redisplay optimizations. I think that a correct implementation would have for each window w (w->last_modified < MODIFF) => (NOT (w->window_end_valid)) but strongly doubt that this implication holds currently. >> For example, wherever last_modified is reset to 0 last_overlay_modified >> is always reset to 0 too. Isn't that plain overkill? > > The potential for separate optimizations is not realized, that's true. > But it exists; I'm not sure we should remove it, and I surely won't > spend any of my personal time trying. Fixing real bugs in the display > engine is enough to fill my free time already. Of course, if you feel > like it, and if no one objects, feel free to make these cleanups. I don't intend to make any cleanups. I'd like to have a simple routine we can use to reset any such structur members within window.c and have that DTRT. Currently, `window-end' is clearly broken and we should fix it. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-12 9:35 ` martin rudalics @ 2012-10-12 13:51 ` Eli Zaretskii 2012-10-12 15:42 ` martin rudalics 2012-10-12 14:55 ` Stefan Monnier 1 sibling, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-12 13:51 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Fri, 12 Oct 2012 11:35:57 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: cschol2112@gmail.com, 12600@debbugs.gnu.org > > > Quite a few struct members related to the > > display engine (and I suppose other core structures as well) are > > insufficiently, in accurately, or even downright incorrectly > > documented. I try to fix every such problem I bump into, FWIW. > > If these concern the display engine exclusively, there's no problem. I think this is why these are there, yes. > Problems arise when the window handling code is supposed to change them. Like where and when? > >> For example, what does the "displayed buffer's text modification events > >> counter as of last time display completed" mean? > > > > This one sounds quite clear, please tell which part needs further > > clarifications. It would be better to say "counter of the displayed > > buffer's modification events as of last time display completed", but > > somehow I'm guessing it's not what you had in mind. > > That's exactly what I had in mind: Either something that corresponds > textually to what is used in buffer.h or just mention the name of the > corresponding field used in buffer.h. OK, will do. > >> Suppose redisplay has set this to 37. Apparently, setting it to 36 > >> means that the next redisplay will notice that for this window > >> display is not accurate and has to be redone because 36 < 37. > > > > Not necessarily. It depends on what is recorded in the buffer's > > BUF_MODIFF slot. > > IIUC this can only increase monotonously But BUF_MODIFF could also change, no? And a window can display another buffer, can't it? > When last_modifed_flag is set, the window must be redisplayed. Not exactly, but OK. > OTOH when the buffer iself is modified it has to be > redisplayed anyway because we hardly know where the change happened. If course, we know: we know where the window begins and ends. > So I don't see why such a comparison of counters is useful. But > maybe I'm missing something. We probably both are, but what's the bottom line here? > >> And why do we have additional fields for last_overlay_modified and > >> window_end_valid? What sense does it make to handle these separately? > > > > Because changes in overlays do not constitute changes in buffer > > contents, and are done via yet another set of primitives, yet they do > > require redisplay. Also because each one of these can allow and > > disallow certain distinct redisplay optimizations, at least in > > principle. > > I doubt whether such optimizations exist. What, you mean in theory? That's a strange opinion, as there are any number of ways of optimizing redisplay. In fact, there are comments today in the display code that describe optimizations that could be implemented, but never were. > Suppose we could exclude a change to happen within the bounds of a > window as for example a buffer displayed with a window starting at M > and ending at N and an overlay modified at some position < M or > N. > Wouldn't this require to associate each single overlay with a > modification counter? Maybe, but I doubt that would allow any gains. To make use of these counters, you'd have to examine every overlay; but as soon as you have an overlay in hand, its buffer position is as easy to access as its counter. The problem with overlays is that overlays-at, next-overlay-change, etc. are slow, not that we lack some info in the overlays themselves. Anyway, it would seem to be bad design to have a _window_ flag that would change when some text or overlay in a buffer is modified. Emacs separates between display-related structures and buffer-related structures for a number of good reasons, the most important being that they are modified and examined independently, and there's no 1:1 relation between buffers and windows. > I think that a correct implementation would have for each window w > > (w->last_modified < MODIFF) => (NOT (w->window_end_valid)) > > but strongly doubt that this implication holds currently. You could try putting assertions like that in the code and see if they fire. > I don't intend to make any cleanups. I'd like to have a simple routine > we can use to reset any such structur members within window.c and have > that DTRT. Under what circumstances does window.c need to do that? > Currently, `window-end' is clearly broken and we should fix it. An optimization that sometimes does the wrong thing is easy to fix: either discover a condition under which the optimization works, or simply disable the optimization. ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-12 13:51 ` Eli Zaretskii @ 2012-10-12 15:42 ` martin rudalics 0 siblings, 0 replies; 34+ messages in thread From: martin rudalics @ 2012-10-12 15:42 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 >> Problems arise when the window handling code is supposed to change them. > > Like where and when? Currently it does reset last_modified and last_overlay_modified in Fset_window_start, set_window_buffer, window_resize_apply, grow_mini_window, shrink_mini_window, window_scroll_pixel_based, window_scroll_line_based and Fset_window_configuration. I meanwhile assume that I should do that in Fdelete_other_windows_internal too. OTOH Frecenter, Fset_window_fringes and Fset_window_scroll_bars do set window_end_valid but leave w->last_modified and w->last_overlay_modified alone. >> That's exactly what I had in mind: Either something that corresponds >> textually to what is used in buffer.h or just mention the name of the >> corresponding field used in buffer.h. > > OK, will do. And if possible add for each of these an advice like "Code that may change the start/end position of a buffer in the window is supposed to reset the value of this to Qnil/0". Please keep in mind that not very many people currently have an idea what these fields are used for. So even if your advices are sloppy they will help to keep one's attention. >> > Not necessarily. It depends on what is recorded in the buffer's >> > BUF_MODIFF slot. >> >> IIUC this can only increase monotonously > > But BUF_MODIFF could also change, no? I meant BUF_MODIFF. > And a window can display > another buffer, can't it? This would obviously have to be caught elsewhere since currently you don't check for buffer identities either when you do && w->last_modified >= MODIFF in redisplay_internal (you probably did that before, but in some independent way). In any case, set_window_buffer would set last_modifed_flag as well so again there's no reason for a counter. >> When last_modifed_flag is set, the window must be redisplayed. > > Not exactly, but OK. You mean that in some cases we could get away without redisplaying it? That's what I tried to address below. >> OTOH when the buffer iself is modified it has to be >> redisplayed anyway because we hardly know where the change happened. > > If course, we know: we know where the window begins and ends. But we don't necessarily know where any buffer change(s) happened at the time we redisplay. >> So I don't see why such a comparison of counters is useful. But >> maybe I'm missing something. > > We probably both are, but what's the bottom line here? That I still don't see why comparing last_modifed and MODIFF is useful and why we have to assign two or three integer/Lisp fields instead of one boolean. >> > Because changes in overlays do not constitute changes in buffer >> > contents, and are done via yet another set of primitives, yet they do >> > require redisplay. Also because each one of these can allow and >> > disallow certain distinct redisplay optimizations, at least in >> > principle. >> >> I doubt whether such optimizations exist. > > What, you mean in theory? That's a strange opinion, as there are any > number of ways of optimizing redisplay. In fact, there are comments > today in the display code that describe optimizations that could be > implemented, but never were. Could you lay out one possible way where using a counter for last_overlay_modified would allow an optimization? I certainly would not question any other optimizations. >> Suppose we could exclude a change to happen within the bounds of a >> window as for example a buffer displayed with a window starting at M >> and ending at N and an overlay modified at some position < M or > N. >> Wouldn't this require to associate each single overlay with a >> modification counter? > > Maybe, but I doubt that would allow any gains. To make use of these > counters, you'd have to examine every overlay; but as soon as you have > an overlay in hand, its buffer position is as easy to access as its > counter. > > The problem with overlays is that overlays-at, next-overlay-change, > etc. are slow, not that we lack some info in the overlays themselves. > > Anyway, it would seem to be bad design to have a _window_ flag that > would change when some text or overlay in a buffer is modified. Emacs > separates between display-related structures and buffer-related > structures for a number of good reasons, the most important being that > they are modified and examined independently, and there's no 1:1 > relation between buffers and windows. I agree with everything you say here. Only that my conclusion is that using a counter in last_overlay_modified is pretty much useless. >> I think that a correct implementation would have for each window w >> >> (w->last_modified < MODIFF) => (NOT (w->window_end_valid)) >> >> but strongly doubt that this implication holds currently. > > You could try putting assertions like that in the code and see if they > fire. Why bother? You would have helped me by telling that such an assertion _should_ hold. If so, I can easily fill in the details. >> I don't intend to make any cleanups. I'd like to have a simple routine >> we can use to reset any such structur members within window.c and have >> that DTRT. > > Under what circumstances does window.c need to do that? In the cases I cited at the beginning of this post. And maybe in some cases I'm not aware of. >> Currently, `window-end' is clearly broken and we should fix it. > > An optimization that sometimes does the wrong thing is easy to fix: > either discover a condition under which the optimization works, or > simply disable the optimization. If the underlying implementation defies the optimization, we should fix that implementation. But for that I'd have to understand the semantics of the optimization first. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-12 9:35 ` martin rudalics 2012-10-12 13:51 ` Eli Zaretskii @ 2012-10-12 14:55 ` Stefan Monnier 2012-10-12 15:36 ` Eli Zaretskii 2012-10-12 15:43 ` martin rudalics 1 sibling, 2 replies; 34+ messages in thread From: Stefan Monnier @ 2012-10-12 14:55 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > When last_modifed_flag is set, the window must be redisplayed. No: last_modifed_flag is (normally) only set at the end of redisplay, so the in the future you can check if redisplay is needed by comparing it with the buffer's modiff. > assignment. OTOH when the buffer iself is modified it has to be > redisplayed anyway because we hardly know where the change happened. But instead of going through all the windows that display this buffer, we just change the buffer's modiff, so it will cause all the (last_modifed_flag == modiff) checks to fail in the windows that display this buffer. BTW, I'm interested in display-optimizations because I sometimes suffer from severe delays, apparently linked to my use of numerous frames.I haven't dug into yet enough to know really what's going on, but I have the impression that I hit a pathological case where optimizations end up completely disabled such that even after as simple commands as C-f (but which might do more than meets the idea because of things like hl-line-mode and reveal-mode, maybe) all the windows/frames get a redisplay. Stefan ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-12 14:55 ` Stefan Monnier @ 2012-10-12 15:36 ` Eli Zaretskii 2012-10-12 15:43 ` martin rudalics 1 sibling, 0 replies; 34+ messages in thread From: Eli Zaretskii @ 2012-10-12 15:36 UTC (permalink / raw) To: Stefan Monnier; +Cc: 12600 > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: Eli Zaretskii <eliz@gnu.org>, 12600@debbugs.gnu.org > Date: Fri, 12 Oct 2012 10:55:20 -0400 > > BTW, I'm interested in display-optimizations because I sometimes suffer > from severe delays, apparently linked to my use of numerous frames.I > haven't dug into yet enough to know really what's going on, but I have > the impression that I hit a pathological case where optimizations end up > completely disabled such that even after as simple commands as C-f (but > which might do more than meets the idea because of things like > hl-line-mode and reveal-mode, maybe) all the windows/frames get > a redisplay. If you can come up with a test case, please file a bug report and I will look into it. ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-12 14:55 ` Stefan Monnier 2012-10-12 15:36 ` Eli Zaretskii @ 2012-10-12 15:43 ` martin rudalics 2012-10-13 8:56 ` Eli Zaretskii 1 sibling, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-12 15:43 UTC (permalink / raw) To: Stefan Monnier; +Cc: 12600 >> When last_modifed_flag is set, the window must be redisplayed. > > No: last_modifed_flag is (normally) only set at the end of redisplay, so > the in the future you can check if redisplay is needed by comparing it > with the buffer's modiff. last_modifed_flag is a fictitious variable I would set when the window changes. When it's set, redisplay must redisplay the window. >> assignment. OTOH when the buffer iself is modified it has to be >> redisplayed anyway because we hardly know where the change happened. > > But instead of going through all the windows that display this buffer, > we just change the buffer's modiff, so it will cause all the > (last_modifed_flag == modiff) checks to fail in the windows that display > this buffer. We'd obviously have an independent buffer_modified_flag. A window must be redisplayed if either buffer_modified_flag is set (modulo any optimizations which I won't dispute here) or its last_modifed_flag is set. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-12 15:43 ` martin rudalics @ 2012-10-13 8:56 ` Eli Zaretskii 2012-10-13 9:51 ` martin rudalics 0 siblings, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-13 8:56 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Fri, 12 Oct 2012 17:43:01 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: Eli Zaretskii <eliz@gnu.org>, 12600@debbugs.gnu.org > > >> When last_modifed_flag is set, the window must be redisplayed. > > > > No: last_modifed_flag is (normally) only set at the end of redisplay, so > > the in the future you can check if redisplay is needed by comparing it > > with the buffer's modiff. > > last_modifed_flag is a fictitious variable I would set when the window > changes. When it's set, redisplay must redisplay the window. What do you mean by "window changes"? And how would any code outside of the display engine know whether some change requires to redisplay a window? Anyway, I don't think the above is right. Only the display engine should set this variable. The display engine should figure out itself whether to redisplay a window, by using other means. If it doesn't, that's a bug. > >> assignment. OTOH when the buffer iself is modified it has to be > >> redisplayed anyway because we hardly know where the change happened. > > > > But instead of going through all the windows that display this buffer, > > we just change the buffer's modiff, so it will cause all the > > (last_modifed_flag == modiff) checks to fail in the windows that display > > this buffer. > > We'd obviously have an independent buffer_modified_flag. A window must > be redisplayed if either buffer_modified_flag is set (modulo any > optimizations which I won't dispute here) or its last_modifed_flag is > set. But comparing the buffer's modiff with last_modified already accomplishes this, so what would be the purpose of converting last_modified to a boolean flag, and then introducing another struct member that acts exactly like last_modified does today? ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-13 8:56 ` Eli Zaretskii @ 2012-10-13 9:51 ` martin rudalics 2012-10-13 12:45 ` Eli Zaretskii 0 siblings, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-13 9:51 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 >> last_modifed_flag is a fictitious variable I would set when the window >> changes. When it's set, redisplay must redisplay the window. > > What do you mean by "window changes"? And how would any code outside > of the display engine know whether some change requires to redisplay a > window? There are three types of window changes we have to consider: (1) Change the window's buffer via `set-window-buffer'. (2) Change the size of the window (including toggling of scrollbars and fringes). (3) Change the buffer's position in the window (usually via scrolling, `set-window-point' and `set-window-start'). There might be indirect changes as well (e.g., when setting a window display property) but let's stick to the three cited above. All these require usually a complete redisplay of the buffer in the window. There is one exception, namely when `split-window-keep-point' is nil, `split-window-below' tries to keep the old display (but I doubt that this works with variable height fonts and it will likely fail as soon as we split windows pixel-wise). Now in all of these cases, the respective routines in window.c would set the window's last_modified_flag to t, marking the window as dirty. When resizing or splitting windows, usually more than one window is affected; for scrolling usually one window is affected. When the display engine scans windows, it has to redisplay a window when the flag is set, resetting the flag when it's done. Otherwise, it will redisplay the window iff the buffer's modification flag says so. Note that the last_modified_flag of the window covers both last_modified and last_overlay_modified as far as the window's redisplay is concerned. `window-end' with non-nil UPDATE requires a different treatment anyway because it inspects a cached value that is invalidated either by a buffer modification or a window change. Hence the only simple solution for this is to reset window_end_pos to nil whenenver we set that window's last_modified_flag. `window-end' then would update window_end_pos either if it is nil or the buffer was modified since the last redisplay. > Anyway, I don't think the above is right. Only the display engine > should set this variable. The display engine should figure out itself > whether to redisplay a window, by using other means. If it doesn't, > that's a bug. So why do we currently reset last_modified and last_overlay_modified in window.c? >> We'd obviously have an independent buffer_modified_flag. A window must >> be redisplayed if either buffer_modified_flag is set (modulo any >> optimizations which I won't dispute here) or its last_modifed_flag is >> set. > > But comparing the buffer's modiff with last_modified already > accomplishes this, so what would be the purpose of converting > last_modified to a boolean flag, and then introducing another struct > member that acts exactly like last_modified does today? The last_modified_flag struct member would replace three members that have very obscure semantics IMHO. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-13 9:51 ` martin rudalics @ 2012-10-13 12:45 ` Eli Zaretskii 2012-10-13 17:45 ` martin rudalics 0 siblings, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-13 12:45 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Sat, 13 Oct 2012 11:51:46 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org > > >> last_modifed_flag is a fictitious variable I would set when the window > >> changes. When it's set, redisplay must redisplay the window. > > > > What do you mean by "window changes"? And how would any code outside > > of the display engine know whether some change requires to redisplay a > > window? > > There are three types of window changes we have to consider: > > (1) Change the window's buffer via `set-window-buffer'. This is taken care of by setting windows_or_buffers_changed. > (2) Change the size of the window (including toggling of scrollbars and > fringes). Redisplay figures this out already, I think. Which commands/functions make these changes? > (3) Change the buffer's position in the window (usually via scrolling, > `set-window-point' and `set-window-start'). These likewise set windows_or_buffers_changed, so they shouldn't be a problem. > Now in all of these cases, the respective routines in window.c would set > the window's last_modified_flag to t, marking the window as dirty. I don't think this is necessary. Can you try without setting this flag, and see if anything breaks? > > Anyway, I don't think the above is right. Only the display engine > > should set this variable. The display engine should figure out itself > > whether to redisplay a window, by using other means. If it doesn't, > > that's a bug. > > So why do we currently reset last_modified and last_overlay_modified in > window.c? See above. Maybe I'm missing something, but windows_or_buffers_changed should take care of all of this. > >> We'd obviously have an independent buffer_modified_flag. A window must > >> be redisplayed if either buffer_modified_flag is set (modulo any > >> optimizations which I won't dispute here) or its last_modifed_flag is > >> set. > > > > But comparing the buffer's modiff with last_modified already > > accomplishes this, so what would be the purpose of converting > > last_modified to a boolean flag, and then introducing another struct > > member that acts exactly like last_modified does today? > > The last_modified_flag struct member would replace three members that > have very obscure semantics IMHO. We are going in circles, so there must be some misunderstanding here. Can you describe your complete change suggestion, wrt these flags? In particular, what about buffer_modified_flag, and how does it enter this picture? ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-13 12:45 ` Eli Zaretskii @ 2012-10-13 17:45 ` martin rudalics 2012-10-13 18:08 ` Eli Zaretskii 0 siblings, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-13 17:45 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 >> (1) Change the window's buffer via `set-window-buffer'. > > This is taken care of by setting windows_or_buffers_changed. windows_or_buffers_changed is a global flag. How does redisplay find out _which_ window got a new buffer? Or does redisplay not care? >> (2) Change the size of the window (including toggling of scrollbars and >> fringes). > > Redisplay figures this out already, I think. Which commands/functions > make these changes? They all end up calling window_resize_apply. >> (3) Change the buffer's position in the window (usually via scrolling, >> `set-window-point' and `set-window-start'). > > These likewise set windows_or_buffers_changed, so they shouldn't be a > problem. But usually they affect only one window. Again, redisplay might not care. But I would be surprised that it doesn't handle such a simple case of optimization. >> Now in all of these cases, the respective routines in window.c would set >> the window's last_modified_flag to t, marking the window as dirty. > > I don't think this is necessary. Can you try without setting this > flag, and see if anything breaks? I said "would". last_modified_flag doesn't exist. >> So why do we currently reset last_modified and last_overlay_modified in >> window.c? > > See above. Maybe I'm missing something, but > windows_or_buffers_changed should take care of all of this. OK. I'll comment them out after the feature freeze and we'll see ;-) > We are going in circles, so there must be some misunderstanding here. > Can you describe your complete change suggestion, wrt these flags? In > particular, what about buffer_modified_flag, and how does it enter > this picture? Replace the three struct members last_modified, last_overlay_modified and window_end_valid by one struct member called last_modified_flag - actually calling it window_modified would be better. Set window_modified to t wherever we currently reset one of the three members. Redisplay, when fully done, would reset window_modified to nil for every window it completes instead of setting the other members. I care about BUF_MODIFF/BUF_OVERLAY_MODIFF only in one place: When calculating `window-end' after a buffer change but before the next redisplay, `window-end' with UPDATE non-nil has to consult BUF_MODIFF/BUF_OVERLAY_MODIFF in order to be sure whether it can reuse window_end_pos. window_end_pos would be nil (invalid) initially, set to a valid value when Fwindow_end updates it, and be reset to nil wherever we change the value of window_modified. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-13 17:45 ` martin rudalics @ 2012-10-13 18:08 ` Eli Zaretskii 2012-10-14 10:21 ` martin rudalics 0 siblings, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-13 18:08 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Sat, 13 Oct 2012 19:45:20 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org > > >> (1) Change the window's buffer via `set-window-buffer'. > > > > This is taken care of by setting windows_or_buffers_changed. > > windows_or_buffers_changed is a global flag. How does redisplay find > out _which_ window got a new buffer? Or does redisplay not care? It doesn't care, in the sense that it always considers every window. It _does_ care, in the sense that certain redisplay optimizations are turned off when windows_or_buffers_changed is non-zero. E.g., if nothing's changed since the last redisplay, then redisplay will only enter try_cursor_movement for each window, quickly see that point didn't move, and exit without doing anything. But if windows_or_buffers_changed is non-zero, this optimizations is disabled. > >> (2) Change the size of the window (including toggling of scrollbars and > >> fringes). > > > > Redisplay figures this out already, I think. Which commands/functions > > make these changes? > > They all end up calling window_resize_apply. They all also set windows_or_buffers_changed non-zero. So I think these cases are already covered, as far as redisplay is concerned. > > >> (3) Change the buffer's position in the window (usually via scrolling, > >> `set-window-point' and `set-window-start'). > > > > These likewise set windows_or_buffers_changed, so they shouldn't be a > > problem. > > But usually they affect only one window. Again, redisplay might not > care. But I would be surprised that it doesn't handle such a simple > case of optimization. It tries. It disables fewer optimizations when last_modified is reset than when windows_or_buffers_changed is non-zero. But I doubt that this difference shows in many important situations. At least resizing a window never affects only one window. > >> Now in all of these cases, the respective routines in window.c would set > >> the window's last_modified_flag to t, marking the window as dirty. > > > > I don't think this is necessary. Can you try without setting this > > flag, and see if anything breaks? > > I said "would". last_modified_flag doesn't exist. The same should be tru for the last_modified and last_overlay_modified fields, which do exist. > >> So why do we currently reset last_modified and last_overlay_modified in > >> window.c? > > > > See above. Maybe I'm missing something, but > > windows_or_buffers_changed should take care of all of this. > > OK. I'll comment them out after the feature freeze and we'll see ;-) Thanks. > Replace the three struct members last_modified, last_overlay_modified > and window_end_valid by one struct member called last_modified_flag - > actually calling it window_modified would be better. Set > window_modified to t wherever we currently reset one of the three > members. Redisplay, when fully done, would reset window_modified to nil > for every window it completes instead of setting the other members. And when a buffer is modified or its overlays are modified, what should we do to indicate to redisplay that the corresponding windows might need a more thorough redisplay? ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-13 18:08 ` Eli Zaretskii @ 2012-10-14 10:21 ` martin rudalics 2012-10-14 12:06 ` Eli Zaretskii 0 siblings, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-14 10:21 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 >> Replace the three struct members last_modified, last_overlay_modified >> and window_end_valid by one struct member called last_modified_flag - >> actually calling it window_modified would be better. Set >> window_modified to t wherever we currently reset one of the three >> members. Redisplay, when fully done, would reset window_modified to nil >> for every window it completes instead of setting the other members. > > And when a buffer is modified or its overlays are modified, what > should we do to indicate to redisplay that the corresponding windows > might need a more thorough redisplay? When a window shows a buffer that has been modified since the last redisplay, that buffer must be redrawn. More precisely, redisplay would walk all live windows and for each window (1) Redraw if something in the window's buffer or a setting affecting the display of all buffers (like the cursor type) was modified. (2) Redraw if the window itself has been modified. (3) Don't redraw the window otherwise. This would cover the case where `point' was moved in a buffer not shown in this window or another window was scrolled. This would replace checking of windows_or_buffers_changed with a finer-grained has "this window or its buffer changed". But after a cursory look at redisplay_window I doubt that such a change would be feasible. And I have no idea to which extent (3) is already covered by try_window_id. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-14 10:21 ` martin rudalics @ 2012-10-14 12:06 ` Eli Zaretskii 2012-10-14 18:33 ` martin rudalics 0 siblings, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-14 12:06 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Sun, 14 Oct 2012 12:21:15 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org > > >> Replace the three struct members last_modified, last_overlay_modified > >> and window_end_valid by one struct member called last_modified_flag - > >> actually calling it window_modified would be better. Set > >> window_modified to t wherever we currently reset one of the three > >> members. Redisplay, when fully done, would reset window_modified to nil > >> for every window it completes instead of setting the other members. > > > > And when a buffer is modified or its overlays are modified, what > > should we do to indicate to redisplay that the corresponding windows > > might need a more thorough redisplay? > > When a window shows a buffer that has been modified since the last > redisplay, that buffer must be redrawn. More precisely, redisplay would > walk all live windows and for each window > > (1) Redraw if something in the window's buffer or a setting affecting > the display of all buffers (like the cursor type) was modified. How do you know whether the window's buffer was modified, under your suggestion? Won't we need some record of "the last buffer state when this window was displayed"? E.g., how do we know that point moved since last full redisplay of the window? > (2) Redraw if the window itself has been modified. You mean, its dimensions or start-point? Or something else? > (3) Don't redraw the window otherwise. This would cover the case where > `point' was moved in a buffer not shown in this window or another > window was scrolled. > > This would replace checking of windows_or_buffers_changed with a > finer-grained has "this window or its buffer changed". But after a > cursory look at redisplay_window I doubt that such a change would be > feasible. And I have no idea to which extent (3) is already covered by > try_window_id. The normal "do-nothing" route is to call try_cursor_movement, then "goto done". try_window_id is called only if there's some change that requires redisplaying some of the text, not just moving the cursor. ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-14 12:06 ` Eli Zaretskii @ 2012-10-14 18:33 ` martin rudalics 2012-10-14 20:01 ` Eli Zaretskii 0 siblings, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-14 18:33 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 > How do you know whether the window's buffer was modified, under your > suggestion? Won't we need some record of "the last buffer state when > this window was displayed"? E.g., how do we know that point moved > since last full redisplay of the window? If we do not know whether point moved in a buffer since its last redisplay, we probably can't optimize anything at all. But we already got MODIFF, CHARS_MODIFF, and OVERLAY_MODIFF. What are these good for if we always have to redisplay a window showing a buffer whose point could have moved since the last redisplay? But apparently try_cursor_movement handles this if I understand your text below correctly. So why are you asking this? >> (2) Redraw if the window itself has been modified. > > You mean, its dimensions or start-point? Or something else? That it shows another buffer. The window code is not able to discriminate anything else but these three. >> (3) Don't redraw the window otherwise. This would cover the case where >> `point' was moved in a buffer not shown in this window or another >> window was scrolled. >> >> This would replace checking of windows_or_buffers_changed with a >> finer-grained has "this window or its buffer changed". But after a >> cursory look at redisplay_window I doubt that such a change would be >> feasible. And I have no idea to which extent (3) is already covered by >> try_window_id. > > The normal "do-nothing" route is to call try_cursor_movement, So try_cursor_movement cares about the no buffer change, no overlay change, no window change, no font change, ... only point movement case. > then > "goto done". try_window_id is called only if there's some change that > requires redisplaying some of the text, not just moving the cursor. That's what I meant earlier where you replied by asking "how do we know that point moved". The various MODIFFs should tell me whether the buffer changed. Some other settings tell me whether some font or the cursor type changed. And window_modified tells me whether something in the window changed that requires to execute try_window_id. If none of these changed, the window can stay alone. All this would work only if point movement has been handled already. This would mean that try_cursor_movement had instead of && !windows_or_buffers_changed check && !w->window_modified and the respective MODIFF conjuncts for w's buffer. BTW, couldn't we instead of && !(!NILP (Vtransient_mark_mode) && !NILP (BVAR (current_buffer, mark_active))) use the more human && (NILP (Vtransient_mark_mode) || NILP (BVAR (current_buffer, mark_active))) here? martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-14 18:33 ` martin rudalics @ 2012-10-14 20:01 ` Eli Zaretskii 2012-10-15 9:41 ` martin rudalics 0 siblings, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-14 20:01 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Sun, 14 Oct 2012 20:33:39 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org > > > How do you know whether the window's buffer was modified, under your > > suggestion? Won't we need some record of "the last buffer state when > > this window was displayed"? E.g., how do we know that point moved > > since last full redisplay of the window? > > If we do not know whether point moved in a buffer since its last > redisplay, we probably can't optimize anything at all. We do know, but only because we record that (in w->last_point). > But we already > got MODIFF, CHARS_MODIFF, and OVERLAY_MODIFF. What are these good for > if we always have to redisplay a window showing a buffer whose point > could have moved since the last redisplay? Those MODIFF features record actual changes, not cursor motion. > But apparently > try_cursor_movement handles this if I understand your text below > correctly. So why are you asking this? Because I don't understand your plan to redesign these variables and flags. I don't see the big picture. > >> (3) Don't redraw the window otherwise. This would cover the case where > >> `point' was moved in a buffer not shown in this window or another > >> window was scrolled. > >> > >> This would replace checking of windows_or_buffers_changed with a > >> finer-grained has "this window or its buffer changed". But after a > >> cursory look at redisplay_window I doubt that such a change would be > >> feasible. And I have no idea to which extent (3) is already covered by > >> try_window_id. > > > > The normal "do-nothing" route is to call try_cursor_movement, > > So try_cursor_movement cares about the no buffer change, no overlay > change, no window change, no font change, ... only point movement case. No, it is only _called_ when there are no changes of the kind you mention above. If any of these changes are detected, try_cursor_movement is bypassed, since it is known that it will not do the job. Here: /* Handle case where text has not changed, only point, and it has not moved off the frame, and we are not retrying after hscroll. (current_matrix_up_to_date_p is nonzero when retrying.) */ if (current_matrix_up_to_date_p && (rc = try_cursor_movement (window, startp, &temp_scroll_step), rc != CURSOR_MOVEMENT_CANNOT_BE_USED)) { switch (rc) { case CURSOR_MOVEMENT_SUCCESS: used_current_matrix_p = 1; goto done; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< case CURSOR_MOVEMENT_MUST_SCROLL: goto try_to_scroll; default: emacs_abort (); } } The marked line is the "green channel". It is taken only if try_cursor_movement succeeds. And current_matrix_up_to_date_p is computed thusly: current_matrix_up_to_date_p = (!NILP (w->window_end_valid) && !current_buffer->clip_changed && !current_buffer->prevent_redisplay_optimizations_p && w->last_modified >= MODIFF && w->last_overlay_modified >= OVERLAY_MODIFF); > > then > > "goto done". try_window_id is called only if there's some change that > > requires redisplaying some of the text, not just moving the cursor. > > That's what I meant earlier where you replied by asking "how do we know > that point moved". The various MODIFFs should tell me whether the > buffer changed. Some other settings tell me whether some font or the > cursor type changed. And window_modified tells me whether something in > the window changed that requires to execute try_window_id. If none of > these changed, the window can stay alone. All this would work only if > point movement has been handled already. I'm not sure I understand where you are getting, but to facilitate this discussion, let me describe the logic of redisplay_window. It goes like this: . if nothing changed except possibly point, call try_cursor_movement; if that succeeds, we are done . otherwise, if the buffer is unchanged, try reusing some of the current glyph matrix, assuming that just the window-start has changed -- this is what try_window_reusing_current_matrix does . if that fails, call try_window_id, which tries reusing of the current glyph matrix, assuming that only some lines at the beginning or the end of the window have changed . if that fails, too, call try_window to redisplay the entire window using the previous window-start point . if try_window finds that point ends up outside the window, "scroll" the window, i.e. find a better window-start point such that point enters the window -- this is what try_scrolling does . if that fails as well, compute the new window-start and redisplay the entire window starting from there > This would mean that try_cursor_movement had instead of > > && !windows_or_buffers_changed > > check > > && !w->window_modified > > and the respective MODIFF conjuncts for w's buffer. What would we gain by this change? > BTW, couldn't we instead of > > && !(!NILP (Vtransient_mark_mode) > && !NILP (BVAR (current_buffer, mark_active))) > > use the more human > > && (NILP (Vtransient_mark_mode) > || NILP (BVAR (current_buffer, mark_active))) > > here? It depends on how you reason about logic. To me, the condition !NILP (Vtransient_mark_mode) && !NILP (BVAR (current_buffer, mark_active)) is clear, whereas its reverse is less so. ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-14 20:01 ` Eli Zaretskii @ 2012-10-15 9:41 ` martin rudalics 2012-10-15 19:39 ` Eli Zaretskii 0 siblings, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-15 9:41 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 >> > How do you know whether the window's buffer was modified, under your >> > suggestion? Won't we need some record of "the last buffer state when >> > this window was displayed"? E.g., how do we know that point moved >> > since last full redisplay of the window? >> >> If we do not know whether point moved in a buffer since its last >> redisplay, we probably can't optimize anything at all. > > We do know, but only because we record that (in w->last_point). > >> But we already >> got MODIFF, CHARS_MODIFF, and OVERLAY_MODIFF. What are these good for >> if we always have to redisplay a window showing a buffer whose point >> could have moved since the last redisplay? > > Those MODIFF features record actual changes, not cursor motion. > >> But apparently >> try_cursor_movement handles this if I understand your text below >> correctly. So why are you asking this? > > Because I don't understand your plan to redesign these variables and > flags. I don't see the big picture. I never proposed to redesign the handling of w->last_point. All I cared about were last_modified, last_overlay_modified, and window_end_valid. >> So try_cursor_movement cares about the no buffer change, no overlay >> change, no window change, no font change, ... only point movement case. > > No, it is only _called_ when there are no changes of the kind you > mention above. If any of these changes are detected, > try_cursor_movement is bypassed, since it is known that it will not do > the job. Sorry for being unclear. That's what I tried to describe with my sentence above. Maybe "bothers" would have been a better term ... > And current_matrix_up_to_date_p is computed thusly: > > current_matrix_up_to_date_p > = (!NILP (w->window_end_valid) > && !current_buffer->clip_changed > && !current_buffer->prevent_redisplay_optimizations_p > && w->last_modified >= MODIFF > && w->last_overlay_modified >= OVERLAY_MODIFF); > >> > then >> > "goto done". try_window_id is called only if there's some change that >> > requires redisplaying some of the text, not just moving the cursor. I got the impression that the big conjunct below if (/* Point may be in this window. */ PT >= CHARPOS (startp) /* Selective display hasn't changed. */ && !current_buffer->clip_changed /* Function force-mode-line-update is used to force a thorough redisplay. It sets either windows_or_buffers_changed or update_mode_lines. So don't take a shortcut here for these cases. */ && !update_mode_lines && !windows_or_buffers_changed && !cursor_type_changed /* Can't use this case if highlighting a region. When a region exists, cursor movement has to do more than just set the cursor. */ && !(!NILP (Vtransient_mark_mode) && !NILP (BVAR (current_buffer, mark_active))) && NILP (w->region_showing) && NILP (Vshow_trailing_whitespace) /* This code is not used for mini-buffer for the sake of the case of redisplaying to replace an echo area message; since in that case the mini-buffer contents per se are usually unchanged. This code is of no real use in the mini-buffer since the handling of this_line_start_pos, etc., in redisplay handles the same cases. */ && !EQ (window, minibuf_window) /* When splitting windows or for new windows, it happens that redisplay is called with a nil window_end_vpos or one being larger than the window. This should really be fixed in window.c. I don't have this on my list, now, so we do approximately the same as the old redisplay code. --gerd. */ && INTEGERP (w->window_end_vpos) && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows && (FRAME_WINDOW_P (f) || !overlay_arrow_in_current_buffer_p ())) indicates all the cases where try_cursor_movement fails immediately. > I'm not sure I understand where you are getting, but to facilitate > this discussion, let me describe the logic of redisplay_window. It > goes like this: > > . if nothing changed except possibly point, call > try_cursor_movement; if that succeeds, we are done But you clumsily check there whether "nothing changed". So I'd move this to the end. I'd start checking conditions like windows_or_buffers_changed and do the through redisplay immediately. > . otherwise, if the buffer is unchanged, try reusing some of the > current glyph matrix, assuming that just the window-start has > changed -- this is what try_window_reusing_current_matrix does What happens when the window width has changed? Is the glyph matrix still OK? In that case not even the window-start position might have changed. > . if that fails, call try_window_id, which tries reusing of the > current glyph matrix, assuming that only some lines at the > beginning or the end of the window have changed > > . if that fails, too, call try_window to redisplay the entire window > using the previous window-start point Provided the window-start position is still the same, I assume. Do we assume that the buffer has changed from here on? > . if try_window finds that point ends up outside the window, > "scroll" the window, i.e. find a better window-start point such > that point enters the window -- this is what try_scrolling does I suppose this could be called by the next as well? > . if that fails as well, compute the new window-start and redisplay > the entire window starting from there OK. I suppose the order is due to the fact that if applying step N fails, you continue with step N + 1. I thought there are enough cases where one decided statically (that is, when redisplay starts) that the last step doing the full redisplay is needed anyway and it doesn't pay to try another step first. >> This would mean that try_cursor_movement had instead of >> >> && !windows_or_buffers_changed >> >> check >> >> && !w->window_modified >> >> and the respective MODIFF conjuncts for w's buffer. > > What would we gain by this change? That for certain windows we could exclude that a redisplay is needed because the window's size or the buffer's start position in the window changed. But if you can't use this information there's obviously no need providing it. BTW, I meanwhile discovered that the update_mode_line field (with a misleading comment IIUC) is the canonical approach to ask for redisplaying a specific window. Or am I wrong again and `force-window-update' never discriminates between updating a single or all windows of a frame. > It depends on how you reason about logic. To me, the condition > > !NILP (Vtransient_mark_mode) > && !NILP (BVAR (current_buffer, mark_active)) > > is clear, whereas its reverse is less so. ... doubling the negation is even less clear ;-) Ayway, I now checked in a fix for this bug based on the assumption that all involved routines set windows_or_buffers_changed. Some, like the frame resizing functions, never did so and I changed that as well. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-15 9:41 ` martin rudalics @ 2012-10-15 19:39 ` Eli Zaretskii 2012-10-16 9:39 ` martin rudalics 0 siblings, 1 reply; 34+ messages in thread From: Eli Zaretskii @ 2012-10-15 19:39 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Mon, 15 Oct 2012 11:41:05 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org > > > And current_matrix_up_to_date_p is computed thusly: > > > > current_matrix_up_to_date_p > > = (!NILP (w->window_end_valid) > > && !current_buffer->clip_changed > > && !current_buffer->prevent_redisplay_optimizations_p > > && w->last_modified >= MODIFF > > && w->last_overlay_modified >= OVERLAY_MODIFF); > > > >> > then > >> > "goto done". try_window_id is called only if there's some change that > >> > requires redisplaying some of the text, not just moving the cursor. > > I got the impression that the big conjunct below > > if (/* Point may be in this window. */ > PT >= CHARPOS (startp) > /* Selective display hasn't changed. */ > && !current_buffer->clip_changed > /* Function force-mode-line-update is used to force a thorough > redisplay. It sets either windows_or_buffers_changed or > update_mode_lines. So don't take a shortcut here for these > cases. */ > && !update_mode_lines > && !windows_or_buffers_changed > && !cursor_type_changed > /* Can't use this case if highlighting a region. When a > region exists, cursor movement has to do more than just > set the cursor. */ > && !(!NILP (Vtransient_mark_mode) > && !NILP (BVAR (current_buffer, mark_active))) > && NILP (w->region_showing) > && NILP (Vshow_trailing_whitespace) > /* This code is not used for mini-buffer for the sake of the case > of redisplaying to replace an echo area message; since in > that case the mini-buffer contents per se are usually > unchanged. This code is of no real use in the mini-buffer > since the handling of this_line_start_pos, etc., in redisplay > handles the same cases. */ > && !EQ (window, minibuf_window) > /* When splitting windows or for new windows, it happens that > redisplay is called with a nil window_end_vpos or one being > larger than the window. This should really be fixed in > window.c. I don't have this on my list, now, so we do > approximately the same as the old redisplay code. --gerd. */ > && INTEGERP (w->window_end_vpos) > && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows > && (FRAME_WINDOW_P (f) > || !overlay_arrow_in_current_buffer_p ())) > > indicates all the cases where try_cursor_movement fails immediately. This is inside try_cursor_movement. Some simple checks (which are also useful for considering other optimizations) are done before try_cursor_movement is called. > > I'm not sure I understand where you are getting, but to facilitate > > this discussion, let me describe the logic of redisplay_window. It > > goes like this: > > > > . if nothing changed except possibly point, call > > try_cursor_movement; if that succeeds, we are done > > But you clumsily check there whether "nothing changed". The name of the variable, current_matrix_up_to_date_p, is revealing. If these conditions are true, the current glyph matrix is reusable. There's nothing clumsy about that. This variable is used further down the code. > So I'd move this to the end. I'd start checking conditions like > windows_or_buffers_changed and do the through redisplay immediately. Conceptually, the order doesn't matter. Practically, it is better to first check the feasibility of optimizations that allow us to get away with cheaper redisplay, because (a) thorough redisplay anyway takes significantly more time, so there's no need to rush doing it, and (b) the tests for the best optimization are faster and cheaper than those for slower alternatives. > > . otherwise, if the buffer is unchanged, try reusing some of the > > current glyph matrix, assuming that just the window-start has > > changed -- this is what try_window_reusing_current_matrix does > > What happens when the window width has changed? Is the glyph matrix > still OK? No, the glyph matrix needs to be reallocated in that case, which causes a thorough redisplay (AFAIR). > > . if that fails, call try_window_id, which tries reusing of the > > current glyph matrix, assuming that only some lines at the > > beginning or the end of the window have changed > > > > . if that fails, too, call try_window to redisplay the entire window > > using the previous window-start point > > Provided the window-start position is still the same, I assume. If this assumptions proves false, we call try_scrolling, see below. > Do we assume that the buffer has changed from here on? Yes. > > . if try_window finds that point ends up outside the window, > > "scroll" the window, i.e. find a better window-start point such > > that point enters the window -- this is what try_scrolling does > > I suppose this could be called by the next as well? > > > . if that fails as well, compute the new window-start and redisplay > > the entire window starting from there Not normally. The new window-start is computed so as to make sure point will appear. But there are a couple of obscure fallbacks if it doesn't (e.g., if the whole window shows one very high line, or there's a lot of invisible text at window-start, etc.). > OK. I suppose the order is due to the fact that if applying step N > fails, you continue with step N + 1. Right. And the flags are designed so that testing for potential applicability of step N is cheaper than for step N+1. > I thought there are enough cases where one decided statically (that > is, when redisplay starts) that the last step doing the full > redisplay is needed anyway and it doesn't pay to try another step > first. Some tests are expensive, so we postpone them as much as possible. > >> This would mean that try_cursor_movement had instead of > >> > >> && !windows_or_buffers_changed > >> > >> check > >> > >> && !w->window_modified > >> > >> and the respective MODIFF conjuncts for w's buffer. > > > > What would we gain by this change? > > That for certain windows we could exclude that a redisplay is needed > because the window's size or the buffer's start position in the window > changed. But if you can't use this information there's obviously no > need providing it. You can't use it easily. There are just too many conditions when redisplay, or at least some part of it, cannot be avoided. > BTW, I meanwhile discovered that the update_mode_line field (with a > misleading comment IIUC) is the canonical approach to ask for > redisplaying a specific window. That's not my reading of the code. The w->update_mode_line flag, if non-zero, forces redisplay of the mode line, and also of the menu bar and the tool bar, of that window. Where did you see that its effect is to redisplay the whole window? > Or am I wrong again and `force-window-update' never discriminates > between updating a single or all windows of a frame. force-window-update with a nil argument sets update_mode_lines and also windows_or_buffers_changed. The latter prevents redisplay optimizations; the former just causes redisplay to consider all windows, but does not prevent optimizations for each and every window, if these optimizations are otherwise possible. force-window-update with a window as its argument just marks that one window's display "inaccurate", requests redisplay of its mode-line, and prevents optimizations of any other window displaying the same buffer. Windows that don't display this buffer can still avoid some or all of redisplay through optimizations. > > It depends on how you reason about logic. To me, the condition > > > > !NILP (Vtransient_mark_mode) > > && !NILP (BVAR (current_buffer, mark_active)) > > > > is clear, whereas its reverse is less so. > > ... doubling the negation is even less clear ;-) It's not doubling the negation, it negates a condition with a clear and easy interpretation. > Ayway, I now checked in a fix for this bug based on the assumption that > all involved routines set windows_or_buffers_changed. Some, like the > frame resizing functions, never did so and I changed that as well. Thanks. I think resizing requests a thorough redisplay anyway, but setting windows_or_buffers_changed cannot hurt. ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-15 19:39 ` Eli Zaretskii @ 2012-10-16 9:39 ` martin rudalics 2012-10-16 17:35 ` Eli Zaretskii 0 siblings, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-16 9:39 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 12600 >> BTW, I meanwhile discovered that the update_mode_line field (with a >> misleading comment IIUC) is the canonical approach to ask for >> redisplaying a specific window. > > That's not my reading of the code. The w->update_mode_line flag, if > non-zero, forces redisplay of the mode line, and also of the menu bar > and the tool bar, of that window. Where did you see that its effect > is to redisplay the whole window? Because the doc-string for Fforce_window_update says "If optional arg OBJECT is a window, force redisplay of that window only." but the code does mark_window_display_accurate (object, 0); w->update_mode_line = 1; if (BUFFERP (w->buffer)) XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1; ++update_mode_lines; and does not set windows_or_buffers_changed. So apparently the above (and not only setting w->update_mode_line to 1 as I concluded incorrectly) are sufficient to force the redisplay of a single window (including all windows showing the same buffer). > force-window-update with a window as its argument just marks that one > window's display "inaccurate", requests redisplay of its mode-line, > and prevents optimizations of any other window displaying the same > buffer. Windows that don't display this buffer can still avoid some > or all of redisplay through optimizations. That's the case I had in mind. So if I follow you correctly, set_window_buffer could instead of doing windows_or_buffers_changed++; call Fforce_window_update with the window whose buffer gets set as its argument. > I think resizing requests a thorough redisplay anyway, Resizing a frame almost certainly does. change_frame_size_1 does adjust_glyphs (f); calculate_costs (f); SET_FRAME_GARBAGED (f); f->resized_p = 1; but none of these seem useful for Fwindow_end (are they useful anywhere at all?), so ... > setting windows_or_buffers_changed cannot hurt. ... I _had to_ set this in order to make the check in Fwindow_end fail. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-16 9:39 ` martin rudalics @ 2012-10-16 17:35 ` Eli Zaretskii 0 siblings, 0 replies; 34+ messages in thread From: Eli Zaretskii @ 2012-10-16 17:35 UTC (permalink / raw) To: martin rudalics; +Cc: 12600 > Date: Tue, 16 Oct 2012 11:39:37 +0200 > From: martin rudalics <rudalics@gmx.at> > CC: monnier@iro.umontreal.ca, 12600@debbugs.gnu.org > > >> BTW, I meanwhile discovered that the update_mode_line field (with a > >> misleading comment IIUC) is the canonical approach to ask for > >> redisplaying a specific window. > > > > That's not my reading of the code. The w->update_mode_line flag, if > > non-zero, forces redisplay of the mode line, and also of the menu bar > > and the tool bar, of that window. Where did you see that its effect > > is to redisplay the whole window? > > Because the doc-string for Fforce_window_update says "If optional arg > OBJECT is a window, force redisplay of that window only." but the code > does > > mark_window_display_accurate (object, 0); > w->update_mode_line = 1; > if (BUFFERP (w->buffer)) > XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1; > ++update_mode_lines; > > and does not set windows_or_buffers_changed. So apparently the above > (and not only setting w->update_mode_line to 1 as I concluded > incorrectly) are sufficient to force the redisplay of a single window > (including all windows showing the same buffer). Yes. The prevent_redisplay_optimizations_p flag is the crucial detail here. > > force-window-update with a window as its argument just marks that one > > window's display "inaccurate", requests redisplay of its mode-line, > > and prevents optimizations of any other window displaying the same > > buffer. Windows that don't display this buffer can still avoid some > > or all of redisplay through optimizations. > > That's the case I had in mind. So if I follow you correctly, > set_window_buffer could instead of doing > > windows_or_buffers_changed++; > > call Fforce_window_update with the window whose buffer gets set as its > argument. Yes, I think so. ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-07 23:03 bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame Christoph Scholtes 2012-10-08 7:31 ` Eli Zaretskii @ 2012-10-15 9:40 ` martin rudalics 2012-11-09 9:49 ` martin rudalics 1 sibling, 1 reply; 34+ messages in thread From: martin rudalics @ 2012-10-15 9:40 UTC (permalink / raw) To: Christoph Scholtes; +Cc: 12600 > emacs -Q > > Load large file, e.g. emacs.c. Buffer content must exceed one > screen. > > Enable linum mode with `M-x linum-mode'. > > Shrink frame. Maximize frame. Fringe on the left side is missing line > numbers. I checked in a fix for this in revision 110551. Please try again. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
* bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame 2012-10-15 9:40 ` martin rudalics @ 2012-11-09 9:49 ` martin rudalics 0 siblings, 0 replies; 34+ messages in thread From: martin rudalics @ 2012-11-09 9:49 UTC (permalink / raw) To: Christoph Scholtes; +Cc: 12600-done > I checked in a fix for this in revision 110551. Please try again. Bug closed. martin ^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2012-11-09 9:49 UTC | newest] Thread overview: 34+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-10-07 23:03 bug#12600: 24.2.50; linum-mode: line numbers in fringe do not refresh when resizing frame Christoph Scholtes 2012-10-08 7:31 ` Eli Zaretskii 2012-10-08 9:17 ` martin rudalics 2012-10-08 13:59 ` Stefan Monnier 2012-10-08 15:48 ` Eli Zaretskii 2012-10-09 9:36 ` martin rudalics 2012-10-09 17:04 ` Eli Zaretskii 2012-10-10 10:22 ` martin rudalics 2012-10-10 15:45 ` Eli Zaretskii 2012-10-11 7:12 ` martin rudalics 2012-10-11 16:56 ` Eli Zaretskii 2012-10-12 7:32 ` martin rudalics 2012-10-12 8:52 ` Eli Zaretskii 2012-10-12 9:35 ` martin rudalics 2012-10-12 13:51 ` Eli Zaretskii 2012-10-12 15:42 ` martin rudalics 2012-10-12 14:55 ` Stefan Monnier 2012-10-12 15:36 ` Eli Zaretskii 2012-10-12 15:43 ` martin rudalics 2012-10-13 8:56 ` Eli Zaretskii 2012-10-13 9:51 ` martin rudalics 2012-10-13 12:45 ` Eli Zaretskii 2012-10-13 17:45 ` martin rudalics 2012-10-13 18:08 ` Eli Zaretskii 2012-10-14 10:21 ` martin rudalics 2012-10-14 12:06 ` Eli Zaretskii 2012-10-14 18:33 ` martin rudalics 2012-10-14 20:01 ` Eli Zaretskii 2012-10-15 9:41 ` martin rudalics 2012-10-15 19:39 ` Eli Zaretskii 2012-10-16 9:39 ` martin rudalics 2012-10-16 17:35 ` Eli Zaretskii 2012-10-15 9:40 ` martin rudalics 2012-11-09 9:49 ` martin rudalics
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.