ebox/ebox-viewport.el
2026-08-26 00:09:53 +08:00

67 lines
2.9 KiB
EmacsLisp

;;; ebox-viewport.el --- Immediate Emacs viewport delivery -*- lexical-binding: t; -*-
;;; Commentary:
;; Emacs owns window events; Ebox owns the mounted viewport. This module is
;; the single bridge between them. Size hooks only sample the latest visible
;; dimensions and synchronously publish one exact incremental viewport update.
;; Emacs serializes the hook; Ebox's retained renderer bounds each transaction.
;;; Code:
(require 'ebox-surface)
(declare-function ebox--buffer-render-state "ebox-incremental" (buffer))
(declare-function ebox-rerender-buffer-with-context
"ebox" (buffer viewport-width &optional viewport-height))
(defvar ebox--window-size-change-in-progress nil
"Non-nil while Ebox is synchronizing visible window viewports.
External GUI events cannot interleave in Emacs's single thread. A nested call
can only originate from the current publication and therefore has no newer
window geometry to publish.")
(defun ebox-viewport-window-width (window)
"Return Ebox's display-safe viewport width for live WINDOW."
(and (window-live-p window)
(ebox-surface--window-content-width window)))
(defun ebox--window-size-change (frame)
"Synchronize mounted Ebox buffers visible in FRAME immediately."
(when (and (frame-live-p frame)
(not noninteractive)
(not ebox--window-size-change-in-progress))
(let ((ebox--window-size-change-in-progress t)
(seen (make-hash-table :test #'eq)))
(dolist (window (window-list frame 'no-minibuf))
(when (window-live-p window)
(let ((buffer (window-buffer window)))
(unless (gethash buffer seen)
(puthash buffer t seen)
(let ((display-window
(and (buffer-live-p buffer)
(ebox-surface--buffer-display-window buffer))))
(when (and (window-live-p display-window)
(eq (window-frame display-window) frame)
(ebox-surface-buffer-mounted-p buffer))
(let* ((state (ebox--buffer-render-state buffer))
(width (ebox-viewport-window-width display-window))
(height (window-body-height display-window)))
(when (and width
state
(not (and
(= width
(or (plist-get state :viewport-width)
-1))
(= height
(or (plist-get state :viewport-height)
-1)))))
(ebox-rerender-buffer-with-context
buffer width height))))))))))))
(when (boundp 'window-size-change-functions)
(add-hook 'window-size-change-functions #'ebox--window-size-change))
(provide 'ebox-viewport)
;;; ebox-viewport.el ends here