From: Po Lu <luangruo@yahoo.com> Date: Mon, 11 Jul 2022 11:36:01 +0000 (+0800) Subject: Improve behavior of `lost-selection-mode' with multiple buffers X-Git-Tag: emacs-29.0.90~1447^2~1017 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=6f57fb71a50a8b2ac8163828a2cecb394bb52d06;p=emacs.git 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'. --- diff --git a/etc/NEWS b/etc/NEWS index 526bda283c3..afe0f115c5a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -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 diff --git a/lisp/select.el b/lisp/select.el index 6002b2615e1..2d501f207f1 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -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. diff --git a/src/keyboard.c b/src/keyboard.c index 7c13ac96114..1d505c13be3 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -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); }