Fix interactive Ebox publication and viewport bounds
This commit is contained in:
parent
3fd63989e8
commit
1edc6d5bb6
@ -223,6 +223,18 @@ immediately after BODY can trigger GC before the updated buffer is visible."
|
||||
(or (plist-get style :background-color)
|
||||
(plist-get style :bgcolor))))
|
||||
|
||||
(defun ebox-buffer--default-foreground-face ()
|
||||
"Return a face that resets only foreground to the resolved default.
|
||||
Fall back to inheriting `default' when a headless frame has no concrete
|
||||
foreground color."
|
||||
(let ((foreground (face-attribute 'default :foreground nil t)))
|
||||
(if (or (null foreground)
|
||||
(eq foreground 'unspecified)
|
||||
(and (stringp foreground)
|
||||
(string-prefix-p "unspecified" foreground)))
|
||||
'(:inherit default)
|
||||
(list :foreground foreground))))
|
||||
|
||||
(defun ebox-buffer-paint-text-properties (style role)
|
||||
"Return Emacs text properties for computed STYLE in paint ROLE.
|
||||
This backend mapper intentionally accepts computed style facts and emits only
|
||||
@ -231,7 +243,7 @@ buffer-facing paint properties. Layout-only properties never pass through."
|
||||
(when-let ((foreground (ebox-buffer--paint-color style role)))
|
||||
(setq face
|
||||
(if (eq foreground 'ebox/default-foreground)
|
||||
(plist-put face :inherit 'default)
|
||||
(append (ebox-buffer--default-foreground-face) face)
|
||||
(plist-put face :foreground foreground))))
|
||||
(when-let ((background (ebox-buffer--paint-background-color style role)))
|
||||
(setq face (plist-put face :background background)))
|
||||
@ -282,7 +294,7 @@ buffer-facing paint properties. Layout-only properties never pass through."
|
||||
(ebox--add-render-face!
|
||||
string 0 length
|
||||
(if (eq color 'ebox/default-foreground)
|
||||
'(:inherit default)
|
||||
(ebox-buffer--default-foreground-face)
|
||||
`(:foreground ,color))
|
||||
t)
|
||||
(ebox--register-render-owned-face-values source string)))
|
||||
@ -296,7 +308,7 @@ buffer-facing paint properties. Layout-only properties never pass through."
|
||||
(ebox--add-render-face!
|
||||
string 0 length
|
||||
(if (eq color 'ebox/default-foreground)
|
||||
'(:inherit default)
|
||||
(ebox-buffer--default-foreground-face)
|
||||
`(:foreground ,color))
|
||||
t))
|
||||
(when bgcolor
|
||||
|
||||
@ -305,8 +305,8 @@ construction time and can use the static projection path."
|
||||
Some Emacs GUI builds return a column-like half-width even when
|
||||
`window-body-width' is called with PIXELWISE non-nil. When the result is
|
||||
clearly inconsistent with the outer pixel width, prefer the outer width and
|
||||
keep a one-pixel exclusive boundary. Headless/test windows retain the body
|
||||
width fallback."
|
||||
reserve two character columns for Emacs continuation/truncation display.
|
||||
Headless/test windows retain the body width fallback."
|
||||
(let ((body
|
||||
(condition-case nil
|
||||
(window-body-width window t)
|
||||
@ -315,11 +315,16 @@ width fallback."
|
||||
(condition-case nil
|
||||
(window-pixel-width window)
|
||||
(error nil))))
|
||||
(let* ((char-width
|
||||
(condition-case nil
|
||||
(frame-char-width (window-frame window))
|
||||
(error 1)))
|
||||
(reserve (max 2 (* 2 (max 1 char-width)))))
|
||||
(max 0
|
||||
(1-
|
||||
(if (and body outer (> outer (* 1.8 body)))
|
||||
(- (if (and body outer (> outer (* 1.8 body)))
|
||||
outer
|
||||
(or body outer 0))))))
|
||||
(or body outer 0))
|
||||
reserve)))))
|
||||
|
||||
(defun ebox-surface--ensure-signals (buffer values)
|
||||
"Return BUFFER's context signals for VALUES and whether they were created."
|
||||
|
||||
15
ebox.el
15
ebox.el
@ -4519,15 +4519,19 @@ FRAMEWORK-ROLLBACK, when supplied, receives the same report if publication or
|
||||
a later transaction phase fails, and is contained if it violates no-throw.
|
||||
|
||||
Return the successful publication report stored by `ebox-buffer-update-report'."
|
||||
(let ((execute
|
||||
(lambda ()
|
||||
(unless (or (null framework-publish) (functionp framework-publish))
|
||||
(signal 'wrong-type-argument (list 'functionp framework-publish)))
|
||||
(unless (or (null framework-rollback) (functionp framework-rollback))
|
||||
(unless (or (null framework-rollback)
|
||||
(functionp framework-rollback))
|
||||
(signal 'wrong-type-argument (list 'functionp framework-rollback)))
|
||||
(when (and framework-rollback (null framework-publish))
|
||||
(error "Ebox framework rollback requires framework publish"))
|
||||
(let ((buffer (get-buffer buffer-or-name)))
|
||||
(unless (buffer-live-p buffer)
|
||||
(error "Ebox declarative commit requires an existing live buffer: %S"
|
||||
(error
|
||||
"Ebox declarative commit requires an existing live buffer: %S"
|
||||
buffer-or-name))
|
||||
(let* ((commit-input
|
||||
(if (ebox-candidate-p next-root)
|
||||
@ -4558,7 +4562,12 @@ Return the successful publication report stored by `ebox-buffer-update-report'."
|
||||
(plist-get commit-input :preserve-identities-p)
|
||||
(plist-get commit-input :state-overrides)
|
||||
participant))))
|
||||
(ebox-surface--framework-participant-report participant))))
|
||||
(ebox-surface--framework-participant-report participant))))))
|
||||
(if noninteractive
|
||||
(ebox--with-render-gc
|
||||
(funcall execute))
|
||||
(ebox--with-deferred-render-gc
|
||||
(funcall execute)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun ebox-rerender-buffer-with-context
|
||||
|
||||
@ -557,6 +557,20 @@
|
||||
(let ((face (get-text-property (match-beginning 0) 'face)))
|
||||
(should (equal (car face) '(:inherit default))))))))
|
||||
|
||||
(ert-deftest ebox-default-foreground-reset-preserves-explicit-background ()
|
||||
"Resolve GUI default foreground without inheriting its background."
|
||||
(let ((original (symbol-function 'face-attribute)))
|
||||
(cl-letf (((symbol-function 'face-attribute)
|
||||
(lambda (face attribute &rest arguments)
|
||||
(if (and (eq face 'default) (eq attribute :foreground))
|
||||
"Black"
|
||||
(apply original face attribute arguments)))))
|
||||
(should
|
||||
(equal
|
||||
(ebox-buffer-paint-text-properties
|
||||
'(:color ebox/default-foreground :bgcolor "#111827") 'content)
|
||||
'(face (:foreground "Black" :background "#111827")))))))
|
||||
|
||||
(ert-deftest ebox-flex-layout-properties-come-from-ecss-cascade ()
|
||||
"An ECSS rule should determine a Flex container's actual main axis."
|
||||
(ebox-test--reset-runtime-state)
|
||||
@ -3000,6 +3014,44 @@
|
||||
(should (= gc-cons-threshold (* 512 1024 1024))))
|
||||
(ebox--deferred-render-gc-restore))))
|
||||
|
||||
(ert-deftest ebox-interactive-commit-owns-deferred-render-gc ()
|
||||
"Keep GC outside an interactive declarative commit and defer restoration."
|
||||
(ebox-test--reset-runtime-state)
|
||||
(let ((buffer nil))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setq buffer
|
||||
(ebox-render-to-buffer
|
||||
(generate-new-buffer-name " *ebox-test*")
|
||||
(ebox-create :content "before")))
|
||||
(let ((noninteractive nil)
|
||||
(gc-cons-threshold 1000)
|
||||
(gc-cons-percentage 0.1)
|
||||
(ebox-deferred-render-gc-cons-threshold 4000)
|
||||
(ebox-render-gc-cons-percentage 0.8)
|
||||
(ebox--deferred-render-gc-state nil)
|
||||
(ebox--deferred-render-gc-timer nil)
|
||||
(ebox--deferred-render-gc-depth 0)
|
||||
observed-threshold)
|
||||
(unwind-protect
|
||||
(progn
|
||||
(ebox-commit
|
||||
buffer (ebox-create :content "after")
|
||||
(lambda (_report)
|
||||
(setq observed-threshold gc-cons-threshold)))
|
||||
(should (= observed-threshold 4000))
|
||||
(should (= gc-cons-threshold 4000))
|
||||
(should (= gc-cons-percentage 0.8))
|
||||
(should ebox--deferred-render-gc-state)
|
||||
(should (timerp ebox--deferred-render-gc-timer)))
|
||||
(when (timerp ebox--deferred-render-gc-timer)
|
||||
(cancel-timer ebox--deferred-render-gc-timer))
|
||||
(setq ebox--deferred-render-gc-state nil
|
||||
ebox--deferred-render-gc-timer nil
|
||||
ebox--deferred-render-gc-depth 0))))
|
||||
(when (and buffer (buffer-live-p buffer))
|
||||
(kill-buffer buffer)))))
|
||||
|
||||
(ert-deftest ebox-deferred-render-gc-can-raise-an-active-burst-budget ()
|
||||
"Measured layout pressure should only raise an active burst budget."
|
||||
(let ((gc-cons-threshold 1000)
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
((symbol-function 'window-body-height)
|
||||
(lambda (_window) 31)))
|
||||
(let ((values (ebox-surface--context-values buffer nil nil)))
|
||||
(should (= 776 (plist-get values :viewport-width)))
|
||||
(should (= 775 (plist-get values :viewport-width)))
|
||||
(should (= 31 (plist-get values :viewport-height)))))
|
||||
(kill-buffer buffer))))
|
||||
|
||||
@ -93,10 +93,24 @@
|
||||
((symbol-function 'window-body-height)
|
||||
(lambda (_window) 62)))
|
||||
(let ((values (ebox-surface--context-values buffer nil nil)))
|
||||
(should (= 1429 (plist-get values :viewport-width)))
|
||||
(should (= 1428 (plist-get values :viewport-width)))
|
||||
(should (= 62 (plist-get values :viewport-height)))))
|
||||
(kill-buffer buffer))))
|
||||
|
||||
(ert-deftest ebox-surface-window-width-reserves-two-display-columns ()
|
||||
"Reserve both continuation columns from a live GUI content width."
|
||||
(cl-letf (((symbol-function 'window-body-width)
|
||||
(lambda (_window pixelwise)
|
||||
(should pixelwise)
|
||||
987))
|
||||
((symbol-function 'window-pixel-width)
|
||||
(lambda (_window) 987))
|
||||
((symbol-function 'window-frame)
|
||||
(lambda (_window) nil))
|
||||
((symbol-function 'frame-char-width)
|
||||
(lambda (&optional _frame) 8)))
|
||||
(should (= (ebox-surface--window-content-width (selected-window)) 971))))
|
||||
|
||||
(ert-deftest ebox-surface-context-prefers-selected-target-window ()
|
||||
"Ignore stale cross-frame lookup when selected window shows BUFFER."
|
||||
(let* ((buffer (generate-new-buffer " *ebox-selected-viewport-test*"))
|
||||
@ -119,7 +133,7 @@
|
||||
(should (eq candidate window))
|
||||
60)))
|
||||
(let ((values (ebox-surface--context-values buffer nil nil)))
|
||||
(should (= 1399 (plist-get values :viewport-width)))
|
||||
(should (= 1398 (plist-get values :viewport-width)))
|
||||
(should (= 60 (plist-get values :viewport-height))))))
|
||||
(when (window-live-p window) (set-window-buffer window old-buffer))
|
||||
(kill-buffer buffer))))
|
||||
@ -150,7 +164,7 @@
|
||||
((symbol-function 'window-body-height)
|
||||
(lambda (_window) 31)))
|
||||
(let ((values (ebox-surface--context-values buffer nil nil)))
|
||||
(should (= 900 (plist-get values :viewport-width)))
|
||||
(should (= 899 (plist-get values :viewport-width)))
|
||||
(should (= 31 (plist-get values :viewport-height)))))
|
||||
(kill-buffer buffer)
|
||||
(when (get-buffer " *other-window*")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user