You can probably do something like
(defvar my-old-region-bounds nil) (advice-add 'handle-shift-selection :around (lambda (orig-fun) (let ((was-active (region-active-p))) (funcall orig-fun) (when (and was-active (not (region-active-p))) (setq-local my-old-region-bounds (cons (point-marker) (mark-marker))) (add-hook 'post-command-hook #'my-move-to-old-region-bound))))) (defun my-move-to-old-region-bound () (remove-hook 'post-command-hook #'my-move-to-old-region-bound) (let ((bounds my-old-region-bounds)) (kill-local-variable 'my-old-region-bounds) (when bounds (when (funcall (cond ((> (point) (car bounds)) #'<) ((= (point) (car bounds)) #'=) (t #'>)) (point) (cdr bounds)) ;; We moved towards the other (old)boundary. (goto-char (cdr bounds)))))) Of course, this is guaranteed 100% untested.
Edited by AhLeung: I tested it, and it works for most motion functions.