Subject: Re: bug#22320: Overlays with an 'invisible property break stacking of overlay faces

From: Clément Pit--Claudel <[email-masked]>
Date: Thu, 7 Jan 2016 14:07:14 -0500

On 01/07/2016 01:52 PM, Eli Zaretskii wrote:
>> Cc: [email-masked]
>> From: Clément Pit--Claudel <[email-masked]>
>> Date: Thu, 7 Jan 2016 12:36:35 -0500
>>
>> Interestingly, even after disabling the fix for the issue that led to it, I can't reproduce the issue posted there. Instead, I get the behaviour that I described in my previous mail.
> 
> I'm not surprised: a lot has changed in the display engine since
> 2005.  The original issue was just the tip of an iceberg: the general
> problem was that the ellipsis would have an unpredictable face which
> depended on the face of the first invisible character.  I think this
> is more confusing than what we have now, because that situation is by
> far much more common.

I find the current situation more confusing, as it introduces many inconsistencies. Inheriting the face of the first hidden character, and applying it to each dot in the ellipsis, seems a lot more consistent to me (and it does feel predictable). Of course there will be gotchas, but no more than with using the default face; on the other hand, the current heuristic is rather unpredictable (at least the region selection example and the face fallback example in my other message both felt confusing to me).

The same problems exist for composition, but keeping the properties of the first character seems to work well there; maybe we could consider harmonizing both behaviors?

(with-current-buffer (get-buffer-create "emulating invisibility with composition works")
(erase-buffer)
(fundamental-mode)
(add-to-invisibility-spec '(outline . t))
(insert "line1 line2 line3")
;; This composition snippet was taken from Arthur's nameless-mode:
(compose-region 7 12 (cdr (apply #'append (mapcar (lambda (x) (list '(Br . Bl) x)) "..."))))
(let ((ov (make-overlay 7 8)))
(overlay-put ov 'face '(:underline t)))
(let ((ov (make-overlay (point-min) (point-max))))
(overlay-put ov 'face '(:background "red")))
(pop-to-buffer (current-buffer)))

compared to

(with-current-buffer (get-buffer-create "using invisibility directly doesn't work")
(erase-buffer)
(fundamental-mode)
(add-to-invisibility-spec '(outline . t))
(insert "line1 line2 line3")
(let ((ov (make-overlay 7 12)))
(overlay-put ov 'invisible 'outline))
(let ((ov (make-overlay 7 8)))
(overlay-put ov 'face '(:underline t)))
(let ((ov (make-overlay (point-min) (point-max))))
(overlay-put ov 'face '(:background "red")))
(pop-to-buffer (current-buffer)))

Thanks for your help with this issue!

Clément.