diff options
Diffstat (limited to 'modules/auto-dim-config.el')
| -rw-r--r-- | modules/auto-dim-config.el | 186 |
1 files changed, 7 insertions, 179 deletions
diff --git a/modules/auto-dim-config.el b/modules/auto-dim-config.el index ebda92c2..c0e6e7a1 100644 --- a/modules/auto-dim-config.el +++ b/modules/auto-dim-config.el @@ -18,179 +18,16 @@ ;; debounce). The dimmed faces (auto-dim-other-buffers and ;; auto-dim-other-buffers-hide) live in the active theme ;; (themes/dupre-faces.el) so they track theme switches. +;; +;; Terminal buffers (ghostel) do not participate in window dimming: ghostel +;; bakes its color palette into the native module per-terminal, not per-window, +;; so there is no per-window color hook to dim through (the vterm engine had +;; one via `vterm--get-color', which this module used to advise). See the +;; terminal-migration follow-up task in todo.org for revisiting this. ;;; Code: -(require 'cl-lib) -(require 'color) - (declare-function auto-dim-other-buffers-mode "auto-dim-other-buffers") -(declare-function adob--update "auto-dim-other-buffers") -(declare-function vterm--get-color "vterm") -(declare-function vterm--invalidate "vterm") -(declare-function vterm--set-size "vterm") -(declare-function vterm--get-margin-width "vterm") -(defvar vterm-min-window-width) -(defvar vterm--term) - -(defvar cj/auto-dim--last-selected-window nil - "Most recent selected window seen by `cj/auto-dim--refresh-vterm-on-command'.") - -(defvar cj/auto-dim--vterm-refresh-timer nil - "Timer used to defer vterm redraws until after auto-dim updates.") - -(defcustom cj/auto-dim-vterm-foreground-blend 0.45 - "Blend amount for dimmed vterm foreground colors. - -0 keeps the original vterm color; 1 uses the -`auto-dim-other-buffers' foreground color." - :type 'number - :group 'auto-dim-other-buffers) - -(defcustom cj/auto-dim-vterm-background-blend 0.7 - "Blend amount for dimmed vterm background colors. - -0 keeps the original vterm color; 1 uses the -`auto-dim-other-buffers' background color." - :type 'number - :group 'auto-dim-other-buffers) - -(defun cj/auto-dim--vterm-buffer-dimmed-p () - "Return non-nil when the current vterm buffer should render dimmed. - -Vterm resolves terminal colors to concrete color strings while redrawing the -buffer, so this integration is buffer-level. If the same vterm buffer is shown -in multiple windows and any one of those windows is selected/undimmed, keep the -buffer bright." - (and (eq major-mode 'vterm-mode) - (let ((windows (get-buffer-window-list (current-buffer) nil 'visible))) - (and windows - (not (catch 'undimmed - (dolist (window windows) - (unless (window-parameter window 'adob--dim) - (throw 'undimmed t))))))))) - -(defun cj/auto-dim--face-color (face attribute fallback-face) - "Return FACE ATTRIBUTE, falling back to FALLBACK-FACE." - (let ((color (face-attribute face attribute nil 'default))) - (if (or (null color) (eq color 'unspecified)) - (face-attribute fallback-face attribute nil 'default) - color))) - -(defun cj/auto-dim--color-rgb (color) - "Return COLOR as a list of RGB floats, or nil if COLOR is unknown." - (cond - ((and (stringp color) - (string-match - "\\`#\\([[:xdigit:]]\\{2\\}\\)\\([[:xdigit:]]\\{2\\}\\)\\([[:xdigit:]]\\{2\\}\\)\\'" - color)) - (mapcar (lambda (index) - (/ (string-to-number (match-string index color) 16) 255.0)) - '(1 2 3))) - ((and (stringp color) - (string-match - "\\`#\\([[:xdigit:]]\\)\\([[:xdigit:]]\\)\\([[:xdigit:]]\\)\\'" - color)) - (mapcar (lambda (index) - (/ (* 17 (string-to-number (match-string index color) 16)) 255.0)) - '(1 2 3))) - (t - (ignore-errors - (mapcar (lambda (component) (/ component 65535.0)) - (color-values color)))))) - -(defun cj/auto-dim--blend-color (color target amount) - "Blend COLOR toward TARGET by AMOUNT and return a hex color string." - (if-let* ((rgb (cj/auto-dim--color-rgb color)) - (target-rgb (cj/auto-dim--color-rgb target))) - (apply #'color-rgb-to-hex - (append - (cl-mapcar - (lambda (source dest) - (+ (* source (- 1 amount)) (* dest amount))) - rgb target-rgb) - '(2))) - color)) - -(defun cj/auto-dim--vterm-dim-color (color foreground-p) - "Return dimmed vterm COLOR. - -When FOREGROUND-P is non-nil, blend toward the dimmed foreground face; otherwise -blend toward the dimmed background face." - (let* ((attribute (if foreground-p :foreground :background)) - (target (cj/auto-dim--face-color 'auto-dim-other-buffers attribute 'default)) - (amount (if foreground-p - cj/auto-dim-vterm-foreground-blend - cj/auto-dim-vterm-background-blend))) - (cj/auto-dim--blend-color color target amount))) - -(defun cj/auto-dim--vterm-get-color (orig-fun index &rest args) - "Advise vterm color lookup ORIG-FUN for dimmed windows. - -INDEX and ARGS are passed through to `vterm--get-color'." - (let ((color (apply orig-fun index args))) - (if (and color (cj/auto-dim--vterm-buffer-dimmed-p)) - (cj/auto-dim--vterm-dim-color color (memq :foreground args)) - color))) - -(defun cj/auto-dim--refresh-vterm-windows (&optional frame) - "Refresh visible vterm buffers in FRAME after dim state changes." - (when (or (fboundp 'vterm--set-size) (fboundp 'vterm--invalidate)) - (dolist (window (window-list frame 'no-minibuf)) - (with-current-buffer (window-buffer window) - (when (eq major-mode 'vterm-mode) - (let ((inhibit-read-only t)) - (if (and (bound-and-true-p vterm--term) - (window-live-p window) - (fboundp 'vterm--get-margin-width)) - (let* ((height (max 2 (window-body-height window))) - (min-width (if (boundp 'vterm-min-window-width) - vterm-min-window-width - 80)) - (width (max min-width - (- (window-body-width window) - (vterm--get-margin-width))))) - ;; `vterm--redraw' only repaints rows libvterm marked dirty. - ;; A resize marks the whole terminal grid dirty, so briefly - ;; nudge height and restore it to force a full repaint after - ;; dim-state changes. - (vterm--set-size vterm--term (1+ height) width) - (vterm--set-size vterm--term height width)) - (when (fboundp 'vterm--invalidate) - (vterm--invalidate))))))))) - -(defun cj/auto-dim--refresh-vterm-after-auto-dim (&optional frame) - "Update auto-dim state, then refresh visible vterm buffers in FRAME." - (setq cj/auto-dim--vterm-refresh-timer nil) - (when (fboundp 'adob--update) - (adob--update)) - (cj/auto-dim--refresh-vterm-windows frame)) - -(defun cj/auto-dim--schedule-vterm-refresh (&optional frame) - "Schedule a deferred vterm refresh for FRAME. - -The delay lets selection-changing commands finish before we recompute -auto-dim state and invalidate vterm." - (when cj/auto-dim--vterm-refresh-timer - (cancel-timer cj/auto-dim--vterm-refresh-timer)) - (setq cj/auto-dim--vterm-refresh-timer - (run-with-timer 0 nil #'cj/auto-dim--refresh-vterm-after-auto-dim frame))) - -(defun cj/auto-dim--refresh-vterm-on-command () - "Refresh visible vterm buffers when selected window changes. - -`window-selection-change-functions' does not catch every selection path used by -windmove/Shift-arrow focus changes in this config, so this post-command hook is -the fallback that makes vterm repaint after auto-dim changes window state." - (let ((window (selected-window))) - (unless (eq window cj/auto-dim--last-selected-window) - (setq cj/auto-dim--last-selected-window window) - (cj/auto-dim--schedule-vterm-refresh)))) - -(defun cj/auto-dim--after-select-window (&rest _) - "Schedule vterm refresh after `select-window'." - (setq cj/auto-dim--last-selected-window (selected-window)) - (cj/auto-dim--schedule-vterm-refresh)) (defun cj/auto-dim--never-dim-dashboard-p (buffer) "Return non-nil when BUFFER is the dashboard, so it stays lit. @@ -212,7 +49,7 @@ focus cue on a split-displayed dashboard, accepted as a fair trade." :custom ;; Dim only non-selected windows within Emacs, not the whole frame when ;; Emacs loses focus -- on Hyprland focus moves to other apps constantly, - ;; and the ai-vterm agents live in their own windows. + ;; and the ai-term agents live in their own windows. (auto-dim-other-buffers-dim-on-focus-out nil) (auto-dim-other-buffers-dim-on-switch-to-minibuffer t) :config @@ -259,14 +96,5 @@ focus cue on a split-displayed dashboard, accepted as a fair trade." #'cj/auto-dim--never-dim-dashboard-p) (auto-dim-other-buffers-mode 1)) -(with-eval-after-load 'vterm - (unless (advice-member-p #'cj/auto-dim--vterm-get-color #'vterm--get-color) - (advice-add #'vterm--get-color :around #'cj/auto-dim--vterm-get-color)) - (unless (advice-member-p #'cj/auto-dim--after-select-window #'select-window) - (advice-add #'select-window :after #'cj/auto-dim--after-select-window)) - (add-hook 'window-selection-change-functions - #'cj/auto-dim--schedule-vterm-refresh) - (add-hook 'post-command-hook #'cj/auto-dim--refresh-vterm-on-command)) - (provide 'auto-dim-config) ;;; auto-dim-config.el ends here |
