josior · 2022-11-04 23:22
I want to have `highlight-nonselected-windows` on, but I want different faces for the marked region on the active window and the inactive windows. How would I do that?
link0ff · 2022-11-06 15:04
This is very easy to do: customize `redisplay-highlight-region-function` to a function that is like the default `redisplay--highlight-overlay-function` but where the line `(setq face 'region)` is replaced with:
(setq face (if (eq window (selected-window)) 'region 'secondary-selection))
josior · 2022-11-07 10:45
Thanks for the help.
I couldn't find a `redisplay-highlight-region-function` option to customize, but I found the function in `simple.el`, though there isn't a `(setq face 'region)` in it.
(defvar redisplay-highlight-region-function
(lambda (start end window rol)
(if (not (overlayp rol))
(let ((nrol (make-overlay start end)))
(funcall redisplay-unhighlight-region-function rol)
(overlay-put nrol 'window window)
(overlay-put nrol 'face 'region)
;; Normal priority so that a large region doesn't hide all the
;; overlays within it, but high secondary priority so that if it
;; ends/starts in the middle of a small overlay, that small overlay
;; won't hide the region's boundaries.
(overlay-put nrol 'priority '(nil . 100))
nrol)
(unless (and (eq (overlay-buffer rol) (current-buffer))
(eq (overlay-start rol) start)
(eq (overlay-end rol) end))
(move-overlay rol start end (current-buffer)))
rol))
"Function to move the region-highlight overlay.
This function is called with four parameters, START, END, WINDOW
and OVERLAY. If OVERLAY is nil, a new overlay is created. In
any case, the overlay is adjusted to reflect the other three
parameters.
The overlay is returned by the function.")
What am I missing?
link0ff · 2022-11-07 16:16
This means you have an older version. But in any case just replace `'region` with `(if (eq window (selected-window)) 'region 'secondary-selection)`.
josior · 2022-11-08 10:24
Thanks again. I added the customized `redisplay-highlight-region-function` and the function to call it in my `init.el`, but it didn't work as I expected.
I expected it to change the selection color (to `'secondary-selecion`) on the window when it becomes inactive, and then change back to the `'region` face when it becomes active. But it seems Emacs is getting confused, and when I mark a region in the active window it was showing the `'secondary-selection` face. It's like it's not tracking the window state properly.
(defvar redisplay-highlight-region-function-custom
(lambda (start end window rol)
(if (not (overlayp rol))
(let ((nrol (make-overlay start end)))
(funcall redisplay-unhighlight-region-function rol)
(overlay-put nrol 'window window)
(overlay-put nrol 'face (if (eq window (selected-window)) 'region 'secondary-selection))
;; Normal priority so that a large region doesn't hide all the
;; overlays within it, but high secondary priority so that if it
;; ends/starts in the middle of a small overlay, that small overlay
;; won't hide the region's boundaries.
(overlay-put nrol 'priority '(nil . 100))
nrol)
(unless (and (eq (overlay-buffer rol) (current-buffer))
(eq (overlay-start rol) start)
(eq (overlay-end rol) end))
(move-overlay rol start end (current-buffer)))
rol))
"Function to move the region-highlight overlay.
This function is called with four parameters, START, END, WINDOW
and OVERLAY. If OVERLAY is nil, a new overlay is created. In
any case, the overlay is adjusted to reflect the other three
parameters.
The overlay is returned by the function.")
(defun redisplay--update-region-highlight (window)
(let ((rol (window-parameter window 'internal-region-overlay)))
(if (not (and (region-active-p)
(or highlight-nonselected-windows
(eq window (selected-window))
(and (window-minibuffer-p)
(eq window (minibuffer-selected-window))))))
(funcall redisplay-unhighlight-region-function rol)
(let* ((pt (window-point window))
(mark (mark))
(start (min pt mark))
(end (max pt mark))
(new
(funcall redisplay-highlight-region-function-custom
start end window rol)))
(unless (equal new rol)
(set-window-parameter window 'internal-region-overlay
new))))))
link0ff · 2022-11-08 16:41
Indeed, this doesn't work in Emacs 28. So you need either to use the development version, or wait until Emacs 29 will be released.