Improve behavior of `lost-selection-mode' with multiple buffers

* etc/NEWS: Announce new hook `post-select-region-hook'.

* lisp/select.el (lost-selection-last-region-buffer): New
variable.
(lost-selection-post-select-region-function): New function.
Deactivate the mark if the buffer changed.
(lost-selection-mode): Add new hook.

* src/keyboard.c (command_loop_1): Run that hook when
appropriate.
(syms_of_keyboard): New hook `post-select-region-hook'.
This commit is contained in:
Po Lu 2022-07-11 19:36:01 +08:00
parent 2f823ffd28
commit 6f57fb71a5
3 changed files with 52 additions and 8 deletions

View file

@ -2665,6 +2665,10 @@ them towards or away from each other.
This hook is run before 'x-popup-menu' is about to display a
deck-of-cards menu on screen.
** New hook 'post-select-region-hook'.
This hook is run immediately after 'select-active-regions' causes the
region to be set as the primary selection.
** New function 'buffer-match-p'.
Check if a buffer satisfies some condition. Some examples for
conditions can be regular expressions that match a buffer name, a

View file

@ -479,6 +479,24 @@ are not available to other programs."
;; Minor mode to make losing ownership of PRIMARY behave more like
;; other X programs.
(defvar lost-selection-last-region-buffer nil
"The last buffer from which the region was selected.")
(defun lost-selection-post-select-region-function (_text)
"Handle the region being selected into PRIMARY.
If the current buffer is different from the last buffer,
deactivate the mark in every other buffer.
TEXT is ignored."
(when (not (eq lost-selection-last-region-buffer
(current-buffer)))
(dolist (buffer (buffer-list))
(unless (or (string-match-p "^ "
(buffer-name buffer))
(eq buffer (current-buffer)))
(with-current-buffer buffer
(deactivate-mark t))))
(setq lost-selection-last-region-buffer (current-buffer))))
(defun lost-selection-function (selection)
"Handle losing of ownership of SELECTION.
If SELECTION is `PRIMARY', deactivate the mark in every
@ -496,22 +514,32 @@ non-temporary buffer."
When this is enabled, selecting some text in another program will
cause the mark to be deactivated in all buffers, mimicking the
behavior of most X Windows programs."
behavior of most X Windows programs.
Selecting text in a buffer that ends up changing the primary
selection will also cause the mark to be deactivated in all other
buffers."
:global t
:group 'x
(if lost-selection-mode
(cond ((featurep 'x) (add-hook 'x-lost-selection-functions
#'lost-selection-function))
((featurep 'pgtk) (add-hook 'pgtk-lost-selection-functions
#'lost-selection-function))
((featurep 'haiku) (add-hook 'haiku-lost-selection-functions
#'lost-selection-function)))
(progn
(cond ((featurep 'x) (add-hook 'x-lost-selection-functions
#'lost-selection-function))
((featurep 'pgtk) (add-hook 'pgtk-lost-selection-functions
#'lost-selection-function))
((featurep 'haiku) (add-hook 'haiku-lost-selection-functions
#'lost-selection-function)))
(add-hook 'post-select-region-hook
#'lost-selection-post-select-region-function))
(cond ((featurep 'x) (remove-hook 'x-lost-selection-functions
#'lost-selection-function))
((featurep 'pgtk) (remove-hook 'pgtk-lost-selection-functions
#'lost-selection-function))
((featurep 'haiku) (remove-hook 'haiku-lost-selection-functions
#'lost-selection-function)))))
#'lost-selection-function)))
(remove-hook 'post-select-region-hook
#'lost-selection-post-select-region-function)
(setq lost-selection-last-region-buffer nil)))
;; Functions to convert the selection into various other selection types.

View file

@ -1590,9 +1590,12 @@ command_loop_1 (void)
{
Lisp_Object txt
= call1 (Vregion_extract_function, Qnil);
if (XFIXNUM (Flength (txt)) > 0)
/* Don't set empty selections. */
call2 (Qgui_set_selection, QPRIMARY, txt);
CALLN (Frun_hook_with_args, Qpost_select_region_hook, txt);
}
if (current_buffer != prev_buffer || MODIFF != prev_modiff)
@ -12080,6 +12083,9 @@ syms_of_keyboard (void)
DEFSYM (Qpre_command_hook, "pre-command-hook");
DEFSYM (Qpost_command_hook, "post-command-hook");
/* Hook run after the region is selected. */
DEFSYM (Qpost_select_region_hook, "post-select-region-hook");
DEFSYM (Qundo_auto__add_boundary, "undo-auto--add-boundary");
DEFSYM (Qundo_auto__undoably_changed_buffers,
"undo-auto--undoably-changed-buffers");
@ -13028,6 +13034,12 @@ not recorded. The non-nil value countermands `inhibit--record-char',
which see. */);
record_all_keys = false;
DEFVAR_LISP ("post-select-region-hook", Vpost_select_region_hook,
doc: /* Abnormal hook run after the region is selected.
This usually happens as a result of `select-active-regions'. The hook
is called with one argument, the string that was selected. */);;
Vpost_select_region_hook = Qnil;
pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper);
}