unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Keith David Bershatsky <esq@lawlist.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: emacs-devel@gnu.org
Subject: Re: update_window:  w->desired_matrix is a partial representation.
Date: Sat, 19 Jan 2019 15:03:17 -0800	[thread overview]
Message-ID: <m2lg3guu6i.wl%esq@lawlist.com> (raw)

>> The cache of fake cursors contains relevant coordinates (x, y, hpos, vpos), which are needed for erasing and/or redrawing.

> Why do you cache screen coordinates and not the buffer positions?  If the screen contents around some cursor don't change, you don't need to redraw the cursor, so you don't need the coordinates.  And if the screen does change, more often than not the coordinates will be inaccurate anyway, and need to be recomputed anew.  So why cache them?

As far as I am aware, screen coordinates of a previously laid fake cursor cannot always be extrapolated from a particular buffer position.

Surgical removal of a particular GLYPH or GLYPHLESS fake cursor at the appropriate time in the near to far distant future necessitates that its screen coordinates be either known (cached) or ascertainable.  Removal is needed for a variety of reasons; e.g., PT has moved; the minor-mode for fake cursors has been turned off; etc.

Redrawing fake cursors (without the need to recalculate coordinates) can most likely be reduced to a handful of situations; e.g., Emacs fixed an overlap and erased an adjacent fake cursor in the process.

In the following example, the GLYPHLESS cursor floats in thin air to the right of buffer position 25 on VPOS 5.  [The illustration uses a few spaces before the | character so that we can create the illusion in this thread of a floating BAR_CURSOR.  In Emacs, however, the row ends immediately after the line number and there are no extra spaces filling the gap between the invisible space at the end of the glyph row (which has no buffer position) and the floating BAR_CURSOR.]

0.  My header-line format.
1.  12345⤸
2.  67890⤸
3.  12345⤸
4.  67890
5.     |
6.  Every good boy deserves fudge.
7.  Once upon a time there lived a ....

When the "!" gets inserted into VPOS 1 and pushes lines 6+ downwards, the GLYPHLESS cursor is now floating in thin air to the right of buffer position 26 on VPOS 6.

0.  My header-line format.
1.  12!34⤸
2.  56789⤸
3.  01234⤸
4.  56789⤸
5.  0
6.     |
7.  Every good boy deserves fudge.
8.  Once upon a time there lived a ....

Fake cursors are presently used for two main purposes:

1.  A fake cursor at a specified buffer position; e.g., to use in conjunction with Magnar's multiple-cursors library.  Instead of using a visual overlay such as a solid rectangle to indicate the presence of a fake cursor, Emacs can now draw a BAR_CURSOR or any other cursor-type and color.

2.  A horizontal ruler, and one or two vertical rulers spanning the length/height of the window.  The horizontal/vertical rulers are comprised of GLYPH and GLYPHLESS fake cursors.  One of the vertical rulers track the cursor position, and the other creates a visible fill column indicator.

    2A.  As to GLYPH cursor, Emacs draws the cursor rectangle (e.g, BAR_CURSOR / HBAR_CURSOR) on top of an existing character glyph, and then overwrites the existing character glyph with another imprint.  This is what gives the character with a cursor a bold appearance.

    2B.  As to a GLYPHLESS cursor, Emacs only draws the cursor rectangle in thin air.  These are used along or to intersect a STRETCH glyph such as a tab, and also where no glyph exists.


>> I have a working draft that uses the existing function update_text_area (within dispnew.c) to track changes to each VPOS, and does the following:
>
>> -  All cached fake cursors for the changed VPOS are deleted from the cache.
>
>> -  The portion of each row that remains the same, do not need the fake cursors to be redrawn (except wherever overlaps occur when rif->write_glyphs gets called) -- instead, just the cache of fake cursors gets updated for that section of the row that remains the same.
>
>> -  Subsequent to each call of rif->write_glyphs, the fake cursors get redrawn for the length of what got rewritten by rif->write_glyphs and the cache gets updated accordingly.
>
>> -  As to the relevant section from the end of the row to the x-limit that gets cleared with rif->clear_end_of_line, fake cursors are redrawn on just the portion that got erased -- the cache is updated for the entire length between the end of the row and the right window edge (assumes no right margin).

> This design assumes that update_window_line will be called for each screen line where you have a cursor and whose contents change in some way.  There's nothing in the display engine that makes sure this assumption is true, since the display engine doesn't really know anything about your fake cursors, does it?  For example, the display engine could decide to use some optimization based on the buffer text, which would invalidate your assumption.

> Did you consider the alternative of calculating the screen coordinates of the cursors like we do for the single "normal" cursor?  That is done in set_cursor_from_row, which is called from display_line and from several redisplay optimizations that avoid calling display_line.  You could call at the same places your function that recalculates the coordinates of your cursors, if any, in that screen line, and then store the calculated coordinates in the window structure, like we do with the "normal" cursor.

I appreciate you letting me know that Emacs may update the window text in areas other than update_window_line; e.g., due to an existing optimization.  I will need to work on tracking all of them down and chisel-away at dealing with each one.

set_cursor_from_row loops through the glyph row containing point.  When fake cursors are initially calculated and whenever a significant buffer change occurs (e.g., when PT moves), Emacs loops through all enabled rows of the current matrix, and loops through each glyph row looking for a particular buffer position and/or relative x coordinate.  Because this is somewhat cumbersome for Emacs to do every command loop, I am working on ideas to optimize the need to recalculate and draw/erase the fake cursors -- i.e., have Emacs do the bare minimum based upon areas of the window that have changed since the previous command loop.

>> If the above-described plan of attack sounds prudent/efficient, then perhaps the appropriate place to update VPOS 6+ of the cache in this situation is wherever redisplay "scrolls the text on the glass directly"?

> See try_window_id.  Search for "Scroll the display" to see how it bypasses update_window for the screen lines it scrolls.  Directly above that you will find code that updates the cursor accordingly.

> If you decide to keep your current design, you should augment it so that any future changes that introduce additional bypasses, such as the ones in try_window_id, will be supported by fake cursors with minimum changes.

AWESOME!  Thank you for pinpointing the exact location where redisplay "scrolls the text on the glass directly".  Greatly appreciated!



             reply	other threads:[~2019-01-19 23:03 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-19 23:03 Keith David Bershatsky [this message]
  -- strict thread matches above, loose matches on Subject: below --
2019-01-17 18:08 update_window: w->desired_matrix is a partial representation Keith David Bershatsky
2019-01-19  9:16 ` Eli Zaretskii
2019-01-17  8:05 Keith David Bershatsky
2019-01-17 13:56 ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m2lg3guu6i.wl%esq@lawlist.com \
    --to=esq@lawlist.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).