fix: retain enclosing effects during ordinary content updates
This commit is contained in:
parent
e7066b27f4
commit
dae9db7a74
@ -3370,6 +3370,21 @@ old allocated width while the owner changes its natural content length."
|
||||
(setq position (max (1+ position) next)))))))
|
||||
(and valid seen common)))
|
||||
|
||||
(defun ebox-surface--owner-needs-ancestor-paint-p (state owner-id)
|
||||
"Return non-nil if STATE's detached OWNER-ID omits enclosing effects.
|
||||
Ordinary span publication does not recompose enclosing paint or surface
|
||||
properties. Its local renderer cannot prove equivalence for such an owner."
|
||||
(let ((parents (plist-get state :parent-table))
|
||||
(nodes (plist-get state :node-table))
|
||||
(node-id owner-id)
|
||||
needed)
|
||||
(while (and (not needed) (setq node-id (gethash node-id parents)))
|
||||
(when-let* ((box (ebox-fragment-style-source-node (gethash node-id nodes))))
|
||||
(setq needed
|
||||
(or (ebox-get box :surface-properties)
|
||||
(ebox-surface--region-face-contributions box '(bt bb) t)))))
|
||||
(not (null needed))))
|
||||
|
||||
(defun ebox-surface--owner-patch-candidate
|
||||
(buffer state owner-id allocated-width
|
||||
&optional variable-content-p variable-content-max-width
|
||||
@ -3409,7 +3424,15 @@ old allocated width while the owner changes its natural content length."
|
||||
(or variable-content-p role-owned-lines-p))
|
||||
(plist-put (copy-sequence node) :width allocated-width)
|
||||
node))))
|
||||
(when (and old-snapshot spans node render-node)
|
||||
(when (and old-snapshot spans node render-node
|
||||
;; Mixed projection has a separate paint recomposition step.
|
||||
;; Ordinary spans have only the detached owner's rendered
|
||||
;; faces; retain the full renderer when enclosing paint would
|
||||
;; otherwise disappear from changed text.
|
||||
(or (not (memq (plist-get state :projection-kind)
|
||||
'(span-patch owner-scoped)))
|
||||
(not (ebox-surface--owner-needs-ancestor-paint-p
|
||||
state owner-id))))
|
||||
(let* ((rendered
|
||||
(prog1
|
||||
(ebox-surface--render-candidate-node state render-node)
|
||||
@ -3543,7 +3566,9 @@ old allocated width while the owner changes its natural content length."
|
||||
(mapcar
|
||||
(lambda (proof)
|
||||
(if (plist-get proof :range-splice-p)
|
||||
(ebox-surface--range-patch-candidate buffer state proof)
|
||||
(unless (ebox-surface--owner-needs-ancestor-paint-p
|
||||
state (plist-get proof :owner-id))
|
||||
(ebox-surface--range-patch-candidate buffer state proof))
|
||||
(ebox-surface--owner-patch-candidate
|
||||
buffer state (plist-get proof :owner-id)
|
||||
(plist-get proof :allocated-width)
|
||||
|
||||
@ -276,6 +276,63 @@
|
||||
(ebox-commit-test--face-value
|
||||
(get-text-property (1- (point)) 'face) :foreground)))))
|
||||
|
||||
(ert-deftest ebox-commit-content-patch-retains-ancestor-paint ()
|
||||
"Changing text keeps the paint supplied by its containing boxes."
|
||||
(with-temp-buffer
|
||||
(ebox-render-to-buffer
|
||||
(current-buffer)
|
||||
(ebox-test-column :width '(200) :bgcolor "#FFFDF8"
|
||||
(ebox-test-box :bgcolor "#E0E8E0"
|
||||
(ebox-test-text "10" :key 'counter :source-identity 'counter))
|
||||
(ebox-test-text "untouched")))
|
||||
(let ((candidate (ebox-candidate-begin (current-buffer))))
|
||||
(ebox-candidate-replace-host-ref
|
||||
candidate 'counter
|
||||
(ebox-test-text "20" :key 'counter :source-identity 'counter))
|
||||
(ebox-commit (current-buffer) candidate))
|
||||
(let* ((state (ebox--buffer-render-state (current-buffer)))
|
||||
(expected (ebox--render-node (plist-get state :root-node)
|
||||
(plist-get state :source-index))))
|
||||
(should (equal-including-properties expected (buffer-string))))))
|
||||
|
||||
(ert-deftest ebox-commit-content-patch-retains-ancestor-surface-properties ()
|
||||
"Changing text retains properties supplied by its containing box."
|
||||
(with-temp-buffer
|
||||
(ebox-render-to-buffer
|
||||
(current-buffer)
|
||||
(ebox-test-column :width '(200) :surface-properties '(help-echo "parent")
|
||||
(ebox-test-text "10" :key 'counter :source-identity 'counter)
|
||||
(ebox-test-text "untouched")))
|
||||
(let ((candidate (ebox-candidate-begin (current-buffer))))
|
||||
(ebox-candidate-replace-host-ref
|
||||
candidate 'counter
|
||||
(ebox-test-text "20" :key 'counter :source-identity 'counter))
|
||||
(ebox-commit (current-buffer) candidate))
|
||||
(let* ((state (ebox--buffer-render-state (current-buffer)))
|
||||
(expected (ebox--render-node (plist-get state :root-node)
|
||||
(plist-get state :source-index))))
|
||||
(should (equal-including-properties expected (buffer-string))))))
|
||||
|
||||
(ert-deftest ebox-commit-range-patch-retains-ancestor-paint ()
|
||||
"An equal-line Range replacement retains enclosing paint."
|
||||
(with-temp-buffer
|
||||
(ebox-render-to-buffer
|
||||
(current-buffer)
|
||||
(ebox-test-column :width '(200) :bgcolor "#FFFDF8"
|
||||
(ebox-test-box :width '(80) :height 1
|
||||
(ebox-test-column
|
||||
(ebox-test-child-range 'items
|
||||
(ebox-test-text "10" :key 'old))))
|
||||
(ebox-test-text "untouched")))
|
||||
(let ((candidate (ebox-candidate-begin (current-buffer))))
|
||||
(ebox-candidate-replace-range-ref
|
||||
candidate 'items (ebox-test-text "20" :key 'new))
|
||||
(ebox-commit (current-buffer) candidate))
|
||||
(let* ((state (ebox--buffer-render-state (current-buffer)))
|
||||
(expected (ebox--render-node (plist-get state :root-node)
|
||||
(plist-get state :source-index))))
|
||||
(should (equal-including-properties expected (buffer-string))))))
|
||||
|
||||
(ert-deftest ebox-commit-paint-retains-disjoint-scroll ()
|
||||
"Pure sibling paint retains scroll caches and stays painted after scrolling."
|
||||
(with-temp-buffer
|
||||
|
||||
Loading…
Reference in New Issue
Block a user