diff options
| author | cashmere <cashmere@autistici.org> | 2026-03-10 12:10:44 +0100 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-03-10 12:10:44 +0100 |
| commit | 007e9081b5333ae5fa91b22d85d7c3359b3e5e12 (patch) | |
| tree | a23eab6788fb554ea44adbce4092635a755268c7 /kitty-graphics.el | |
| parent | e8f259d8c03126d548ec28dd9a4bcc41096ab9f9 (diff) | |
| download | kitty-graphics-experiment/pre-redisplay-functions.tar.gz | |
experiment: add pre-redisplay-functions as alternative refresh triggerexperiment/pre-redisplay-functions
Add feature flag (kitty-gfx-use-pre-redisplay) to compare
post-command-hook vs pre-redisplay-functions as the scheduling
trigger for image refresh. Includes instrumentation counters
(trigger count, skipped count) logged per refresh cycle for
quantitative comparison.
Results: pre-redisplay-functions fires ~36x more often than
post-command-hook for identical user activity (3176 vs 89 refresh
cycles in comparable sessions). Emacs redraws far more often than
users run commands (cursor blink, timers, internal redraws), and
pre-redisplay-functions fires per-window on every redisplay.
The current post-command-hook approach remains superior.
Diffstat (limited to 'kitty-graphics.el')
| -rw-r--r-- | kitty-graphics.el | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/kitty-graphics.el b/kitty-graphics.el index 52f2d60..fd6899a 100644 --- a/kitty-graphics.el +++ b/kitty-graphics.el @@ -94,6 +94,16 @@ This debounces rapid redisplay events. Default is ~1 frame at 60fps." :type 'number :group 'kitty-graphics) +(defcustom kitty-gfx-use-pre-redisplay nil + "When non-nil, use `pre-redisplay-functions' instead of `post-command-hook'. +This is an experimental option for comparing refresh trigger strategies. +`pre-redisplay-functions' is more targeted (fires only when a window +actually needs redisplay and receives the specific window), whereas +`post-command-hook' fires on every command unconditionally. +Toggle at runtime by disabling/re-enabling `kitty-graphics-mode'." + :type 'boolean + :group 'kitty-graphics) + (defcustom kitty-gfx-debug nil "When non-nil, log debug info to *kitty-gfx-debug* buffer." :type 'boolean @@ -158,6 +168,15 @@ Most recently used at the front.") Each overlay gets a unique PID so repeated placements replace rather than accumulate.") +(defvar kitty-gfx--trigger-count 0 + "Count of refresh scheduling triggers since last reset. +Used for comparing `post-command-hook' vs `pre-redisplay-functions'.") + +(defvar kitty-gfx--trigger-skipped 0 + "Count of triggers that were skipped (no overlays in window). +Only counted when using `pre-redisplay-functions' or instrumented +`post-command-hook'.") + ;;;; Terminal detection (defun kitty-gfx--supported-p () @@ -409,8 +428,12 @@ to prevent flicker." (cl-incf hidden))))))) nil 'visible) (kitty-gfx--sync-end)) - (kitty-gfx--log "refresh: done total=%d placed=%d hidden=%d pruned=%d" - total-overlays placed hidden pruned)))) + (kitty-gfx--log "refresh: done total=%d placed=%d hidden=%d pruned=%d triggers=%d skipped=%d strategy=%s" + total-overlays placed hidden pruned + kitty-gfx--trigger-count kitty-gfx--trigger-skipped + (if kitty-gfx-use-pre-redisplay "pre-redisplay" "post-command")) + (setq kitty-gfx--trigger-count 0 + kitty-gfx--trigger-skipped 0)))) (defun kitty-gfx--refresh-overlay (ov win-bottom) "Refresh a single overlay OV. WIN-BOTTOM is the window's bottom edge. @@ -557,8 +580,18 @@ buffer before settling to one)." (defun kitty-gfx--on-redisplay () "Post-command hook to schedule image refresh." + (cl-incf kitty-gfx--trigger-count) (kitty-gfx--schedule-refresh)) +(defun kitty-gfx--on-pre-redisplay (win) + "Pre-redisplay hook to schedule image refresh for WIN. +Only schedules if WIN's buffer has kitty-gfx overlays, which avoids +unnecessary work for buffers without images." + (cl-incf kitty-gfx--trigger-count) + (if (buffer-local-value 'kitty-gfx--overlays (window-buffer win)) + (kitty-gfx--schedule-refresh) + (cl-incf kitty-gfx--trigger-skipped))) + ;;;; Image processing (defun kitty-gfx--read-file-base64 (file) @@ -916,15 +949,23 @@ The buffer should be writable (caller handles `inhibit-read-only')." (add-hook 'window-scroll-functions #'kitty-gfx--on-window-scroll) (add-hook 'window-size-change-functions #'kitty-gfx--on-window-change) (add-hook 'window-buffer-change-functions #'kitty-gfx--on-buffer-change) - (add-hook 'post-command-hook #'kitty-gfx--on-redisplay) - (add-hook 'kill-buffer-hook #'kitty-gfx--kill-buffer-hook)) + (if kitty-gfx-use-pre-redisplay + (add-hook 'pre-redisplay-functions #'kitty-gfx--on-pre-redisplay) + (add-hook 'post-command-hook #'kitty-gfx--on-redisplay)) + (add-hook 'kill-buffer-hook #'kitty-gfx--kill-buffer-hook) + (setq kitty-gfx--trigger-count 0 + kitty-gfx--trigger-skipped 0) + (kitty-gfx--log "install-hooks: strategy=%s" + (if kitty-gfx-use-pre-redisplay "pre-redisplay" "post-command"))) (defun kitty-gfx--uninstall-hooks () "Remove redisplay hooks." (remove-hook 'window-scroll-functions #'kitty-gfx--on-window-scroll) (remove-hook 'window-size-change-functions #'kitty-gfx--on-window-change) (remove-hook 'window-buffer-change-functions #'kitty-gfx--on-buffer-change) + ;; Remove both — safe even if only one was installed. (remove-hook 'post-command-hook #'kitty-gfx--on-redisplay) + (remove-hook 'pre-redisplay-functions #'kitty-gfx--on-pre-redisplay) (remove-hook 'kill-buffer-hook #'kitty-gfx--kill-buffer-hook)) ;;;; Org-mode integration |
