emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/auto-dim-other-buffers 31de605fc0 3/3: Add changing of the


From: ELPA Syncer
Subject: [nongnu] elpa/auto-dim-other-buffers 31de605fc0 3/3: Add changing of the fringes in the selected window.
Date: Wed, 18 Dec 2024 19:01:07 -0500 (EST)

branch: elpa/auto-dim-other-buffers
commit 31de605fc0904b15a679d9079c6f7ca9f7abfb29
Author: Michal Nazarewicz <mina86@mina86.com>
Commit: Michal Nazarewicz <mina86@mina86.com>

    Add changing of the fringes in the selected window.
    
    In addition to dimming non-selected windows, add fringe face to the
    list of affected fringes highlighting it in the selected window.
    
    This feature forces a more aggressive redrawing of the frames which
    may cause flickering on systems which previously could handle
    auto-dim-other-buffers without issues.  If this happens, remove the
    fringe face from list of affected face by customising the
    auto-dim-other-buffers-affected-faces variable or executing the
    following:
    
        (setq auto-dim-other-buffers-affected-faces
              (assq-delete-all 'fringe auto-dim-other-buffers-affected-faces))
    
    Fixes: https://github.com/mina86/auto-dim-other-buffers.el/issues/27
---
 README.md                 |  19 +++++
 auto-dim-other-buffers.el | 172 +++++++++++++++++++++++++++++++++-------------
 2 files changed, 144 insertions(+), 47 deletions(-)

diff --git a/README.md b/README.md
index aeae18d4f3..80a78cff0f 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,10 @@ a non-intrusive but still noticeable visual indicator.
 
 [![Demo](screenshot.gif)](https://www.youtube.com/watch?v=2djOHSWhyD4)
 
+The mode provides two indications of the selected window.  Firstly,
+background of non-selected windows is dimmed.  Secondly, fringes of the
+selected windows are highlighted (not visualised in the image above).
+
 
 ## Installation
 
@@ -43,9 +47,24 @@ group which can be accessed with:
 
     M-x customize-group RET auto-dim-other-buffers RET
 
+Highlighting of fringes can be done by removing `fringe` entry from
+`auto-dim-other-buffers-affected-faces` list.  Either via customising
+the variable or using the following snippet:
+
+    (setq auto-dim-other-buffers-affected-faces
+          (assq-delete-all 'fringe auto-dim-other-buffers-affected-faces))
+
 
 ## Troubleshooting
 
+### My screen is flickering
+
+By its nature, `auto-dim-other-buffers-mode` often forces full-window
+refreshes which may cause flickering on some systems and displays.  To
+mitigate it, try disabling `fringe` highlighting which—due to Emacs’
+display code limitation—require full-frame refresh.  See Customisation
+section above for instruction how to do it.
+
 ### Text which should be hidden in org-mode is not
 
 To hide text, `org-mode` uses `org-hide` face whose foreground is set to
diff --git a/auto-dim-other-buffers.el b/auto-dim-other-buffers.el
index 51aaa6d394..d16bede4ab 100644
--- a/auto-dim-other-buffers.el
+++ b/auto-dim-other-buffers.el
@@ -1,7 +1,7 @@
 ;;; auto-dim-other-buffers.el --- Makes windows without focus less prominent 
-*- lexical-binding: t -*-
 ;; Author: Michal Nazarewicz <mina86@mina86.com>
 ;; URL: https://github.com/mina86/auto-dim-other-buffers.el
-;; Version: 2.1.1
+;; Version: 2.2.0
 ;; Package-Requires: ((emacs "27.1"))
 ;; Keywords: faces
 
@@ -27,6 +27,9 @@
 ;; recognise which is the selected window by providing a non-intrusive but 
still
 ;; noticeable visual indicator.
 
+;; The mode provides two indications of the selected window.  Firstly,
+;; background of non-selected windows is dimmed.  Secondly, fringes of the
+;; selected windows are highlighted.
 
 ;; # Installation
 
@@ -56,14 +59,24 @@
 
 ;;     M-x customize-group RET auto-dim-other-buffers RET
 
-;; Note that despite it, the mode operates on *windows* rather than buffers.  
In
-;; other words, selected window is highlighted and all other windows are dimmed
-;; even if they display the same buffer.  The package is named
-;; `auto-dim-other-buffer' for historical reasons.
+;; Highlighting of fringes can be done by removing `fringe' entry from
+;; `auto-dim-other-buffers-affected-faces' list.  Either via customising
+;; the variable or using the following snippet:
+
+;;     (setq auto-dim-other-buffers-affected-faces
+;;           (assq-delete-all 'fringe auto-dim-other-buffers-affected-faces))
 
 
 ;; ## Troubleshooting
 
+;; ### My screen is flickering
+
+;; By its nature, `auto-dim-other-buffers-mode' often forces full-window
+;; refreshes which may cause flickering on some systems and displays.  To
+;; mitigate it, try disabling `fringe' highlighting which—due to Emacs’
+;; display code limitation—require full-frame refresh.  See Customisation
+;; section above for instruction how to do it.
+
 ;; ### Text which should be hidden in org-mode is not
 
 ;; To hide text, `org-mode' uses `org-hide' face whose foreground is set to
@@ -105,12 +118,11 @@
   '((((background light)) :background "#eff") (t :background "#122"))
   "Face with a (presumably) dimmed background for non-selected window.
 
-By default the face is applied to, among others, the ‘default’
-face and is intended to affect the background of the non-selected
-windows.  A related ‘auto-dim-other-buffers-hide-face’ face is
-intended for faces which need their foreground to be changed in
-sync.  Which faces are actually modified is configured by the
-‘auto-dim-other-buffers-affected-faces’ variable."
+By default it is applied to, among others, the ‘default’ face and is
+intended to affect background of non-selected windows.  A related
+‘auto-dim-other-buffers-hide-face’ face is intended for faces which need
+their foreground to be changed in sync.  Which faces are modified is
+configured by the ‘auto-dim-other-buffers-affected-faces’ variable."
   :group 'auto-dim-other-buffers)
 
 (defface auto-dim-other-buffers-hide-face
@@ -128,7 +140,7 @@ to modify foreground of faces which hide the text by 
rendering it
 in the same colour as the background.  Since the mode alters the
 background in a window such faces need to be updated as well.
 
-Which faces are actually modified is configured by the
+Which faces are modified is configured by the
 ‘auto-dim-other-buffers-affected-faces’ variable."
   :group 'auto-dim-other-buffers)
 
@@ -159,6 +171,52 @@ dimmed."
    'auto-dim-other-buffers-never-dim-buffer-functions buffer))
 
 
+(defface adob--hack nil "A hack to make fringe refresh work.  Do not use.")
+(defvar adob--has-fringes nil
+  "Whether we are remapping `fringe' face; see `adob--has-fringes--refresh'.")
+
+(defun adob--has-fringes--refresh ()
+  "Refresh value of `adob--has-fringes'
+based on ‘auto-dim-other-buffers-affected-faces’ variable."
+  (setq
+   adob--has-fringes
+   (let ((spec (cdr-safe (assq 'fringe 
auto-dim-other-buffers-affected-faces))))
+     (and spec (or (symbolp spec) (car-safe spec) (cdr-safe spec)) t))))
+
+(defun adob--force-window-update (object)
+  "Force window to be updated on next redisplay.
+This does more than `force-window-update' by also forcing redisplay of
+fringes if necessary (see `adob--has-fringes').  This is done by forcing
+redisplay of frames containing affected windows."
+  (force-window-update object)
+  (when adob--has-fringes
+    (adob--force-fringes-refresh (if (windowp object)
+                                     (list object)
+                                   (get-buffer-window-list object nil t)))))
+
+(defun adob--positive-assqp (symbol params)
+  "Check that SYMBOL entry in PARAMS alist is a positive number."
+  (let ((value (cdr-safe (assq symbol params))))
+    (and (numberp value) (> value 0))))
+
+(defun adob--force-fringes-refresh (windows)
+  "Force refresh of fringes in WINDOWS.
+This is done by forcing full frame redraws."
+  (dolist (frame (delete-dups (mapcar #'window-frame windows)))
+    (let ((params (frame-parameters frame)))
+      (when (or (adob--positive-assqp 'right-fringe params)
+                (adob--positive-assqp 'left-fringe params))
+        ;; By changing the 'adob--hack face, we force the redisplay of the
+        ;; frame.  (Tracing the C code, I believe what we’re after is setting
+        ;; f->face_change and calling fset_redisplay).  We could instead call
+        ;; redraw-frame but my intuition tells me that that’s a slower
+        ;; operation, though honestly I dunno.
+        ; (redraw-frame frame)
+        (let ((value (face-attribute 'adob--hack :inverse-video frame nil)))
+          (internal-set-lisp-face-attribute
+           'adob--hack :inverse-video (not value) frame))))))
+
+
 (defvar-local adob--face-mode-remapping nil
   "Current face remapping cookie for `auto-dim-other-buffers-mode'.")
 
@@ -200,21 +258,26 @@ This needs to be called after 
‘auto-dim-other-buffers-affected-faces’ is
 changed to update state of all affected buffers (which is done when the
 variable is changed via Customize).  It is also used when disabling the
 adob mode."
-  (save-current-buffer
-    (dolist (buffer (buffer-list))
-      ;; Check if adob--face-mode-remapping has local value indicating we have
-      ;; influence over the buffer. The value may be nil (if there are no
-      ;; affected faces) which is why we’re not simply reading the value.
-      (when (local-variable-p 'adob--face-mode-remapping buffer)
-        (set-buffer buffer)
-        (let* ((had-some (prog1 adob--face-mode-remapping
-                           (adob--remap-remove-relative)))
-               (has-some (and add
-                              (not (adob--never-dim-p buffer))
-                              (adob--remap-add-relative))))
-          (when (or had-some has-some)
-            (force-window-update buffer)))))))
-
+  (let (buffers)
+    (save-current-buffer
+      (dolist (buffer (buffer-list))
+        ;; Check if adob--face-mode-remapping has local value indicating we 
have
+        ;; influence over the buffer. The value may be nil (if there are no
+        ;; affected faces) which is why we’re not simply reading the value.
+        (when (local-variable-p 'adob--face-mode-remapping buffer)
+          (set-buffer buffer)
+          (let* ((had-some (prog1 adob--face-mode-remapping
+                             (adob--remap-remove-relative)))
+                 (has-some (and add
+                                (not (adob--never-dim-p buffer))
+                                (adob--remap-add-relative))))
+            (when (or had-some has-some)
+              (push buffer buffers)
+              (force-window-update buffer))))))
+    (when (adob--has-fringes--refresh)
+      (adob--force-fringes-refresh
+       (apply #'nconc (mapcar (lambda (b) (get-buffer-window-list b 'n t))
+                              buffers))))))
 
 (defun adob--remap-faces (buffer object)
   "Make sure face remappings are active in BUFFER unless its never-dim.
@@ -236,7 +299,7 @@ Return non-nil if remappings have been added to BUFFER."
       (if wants
           (adob--remap-add-relative)
         (adob--remap-remove-relative))
-      (force-window-update object)
+      (adob--force-window-update object)
       wants)))
 
 (defun adob--kill-all-local-variables-advice (kill &rest args)
@@ -270,11 +333,11 @@ Dim previously selected window if selection has changed."
         (when (and (window-live-p adob--last-window)
                    (not (window-minibuffer-p adob--last-window)))
           (set-window-parameter adob--last-window 'adob--dim t)
-          (force-window-update adob--last-window))
+          (adob--force-window-update adob--last-window))
         (setq adob--last-window wnd)
         (unless (window-minibuffer-p adob--last-window)
           (set-window-parameter adob--last-window 'adob--dim nil)
-          (force-window-update adob--last-window)))
+          (adob--force-window-update adob--last-window)))
 
       ;; If buffer has changed, update its status.
       (unless (eq buf adob--last-buffer)
@@ -296,7 +359,7 @@ Dim previously selected window if selection has changed."
           (let ((new (not (eq wnd selected-window))))
             (unless (eq new (window-parameter wnd 'adob--dim))
               (set-window-parameter wnd 'adob--dim new)
-              (force-window-update wnd)))
+              (adob--force-window-update wnd)))
           ;; Make sure that the buffer has remapped faces.
           (adob--remap-faces buf wnd))))))
 
@@ -379,19 +442,24 @@ and frame’s doesn’t have focus."
 (define-minor-mode auto-dim-other-buffers-mode
   "Visually makes windows without focus less prominent.
 
-Windows without input focus are made to look less prominent by
-applying ‘auto-dim-other-buffers-face’ to them.  With many windows
-in a frame, the idea is that this mode helps recognise which is
-the selected window by providing a non-intrusive but still
-noticeable visual indicator.
-
-Note that despite it’s name, since Emacs 27 this mode operates
-on *windows* rather than buffers.  In older versions of Emacs, if
-a buffer was displayed in multiple windows, none of them would be
-dimmed even though at most one could have focus.  This historic
-behaviour is where the mode gets its name from."
+Windows without input focus are made to look less prominent by applying
+‘auto-dim-other-buffers-face’ to them.  With many windows in a frame,
+the idea is that this mode helps recognise which is the selected window
+by providing a non-intrusive but still noticeable visual indicator.
+
+Beware: This mode may cause flickering, especially if fringe changing is
+enabled (which is the default).  To mitigate the flickering, try
+removing fringe changing (see `auto-dim-other-buffers-affected-faces').
+
+Note: Despite it’s name, this mode operates on *windows* rather than
+buffers, i.e. even if a buffer is shown in multiple windows, only one of
+them is considered selected and all other will be dimmed.  Historically,
+prior to Emacs 27, all or none windows displaying a buffer would be
+dimmed; this historical behaviour is where the mode gets its name from."
   :global t
   :group 'auto-dim-other-buffers
+  (adob--has-fringes--refresh)
+
   ;; Add/remove all hooks
   (let ((callback (if auto-dim-other-buffers-mode #'add-hook #'remove-hook)))
     (funcall callback 'window-configuration-change-hook #'adob--rescan-windows)
@@ -444,14 +512,15 @@ update display state of all affected buffers."
   :set (lambda (symbol value)
          (set-default symbol value)
          (when auto-dim-other-buffers-mode
-           (save-current-buffer
+           (save-current-buffer*
              (adob--initialize)))
          value))
 
 (defcustom auto-dim-other-buffers-affected-faces
   '((default   . (auto-dim-other-buffers-face      . nil))
     (org-block . (auto-dim-other-buffers-face      . nil))
-    (org-hide  . (auto-dim-other-buffers-hide-face . nil)))
+    (org-hide  . (auto-dim-other-buffers-hide-face . nil))
+    (fringe    . (auto-dim-other-buffers-face . mode-line-active)))
   "A list of faces affected when dimming/highlighting a window.
 
 The list comprising of (FACE . (DIM-FACE . HIGH-FACE)) cons pairs.
@@ -472,9 +541,18 @@ it’s then up to the user to properly set up faces such 
that all of the
 highlighting works.
 
     (setq auto-dim-other-buffers-affected-faces
-         '((default   . (nil . auto-dim-other-buffers-face))
-           (org-block . (nil . auto-dim-other-buffers-face))
-           (org-hide  . (nil . auto-dim-other-buffers-hide-face))))
+          '((default   . (nil . auto-dim-other-buffers-face))
+            (org-block . (nil . auto-dim-other-buffers-face))
+            (org-hide  . (nil . auto-dim-other-buffers-hide-face))
+            (fringe    . (nil . mode-line-active))))
+
+Beware: inclusion of `fringe' face in the list forces a more expensive
+redraw procedure to be used.  This may cause additional flickering on
+some systems.  If you’re observing flickering, try removing the `fringe'
+entry, e.g. by using code such as:
+
+    (setq auto-dim-other-buffers-affected-faces
+          (assq-delete-all 'fringe auto-dim-other-buffers-affected-faces))
 
 For backwards compatibility, a (FACE . DIM-FACE) format for the entries
 is also accepted.  (Although, setting that is not supported through



reply via email to

[Prev in Thread] Current Thread [Next in Thread]