reddit / emacs

How to set a different face for `region` when window is inactive?

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.