Subject: Re: bug#23478: 25.0.93; Mouse region selection asymmetry

From: Stephen Berman <[email-masked]>
Date: Wed, 06 Jul 2016 18:40:53 +0200

On Tue, 05 Jul 2016 20:23:23 +0300 Eli Zaretskii <[email-masked]> wrote:

>> From: Stephen Berman <[email-masked]>
>> Cc: [email-masked],  [email-masked]
>> Date: Mon, 04 Jul 2016 18:56:03 +0200
>> 
>> > So I still think we should default to the old behavior.
>> 
>> Even with the above adjustment?
>
> Yes.  For me, the important part is that the age-old behavior will
> change.  We have no idea how many users will like it and how many
> won't.  In particular, the new behavior that moves point where it
> previously didn't might annoy people who intend to type after the
> click.  Thus, my preference is to make this an opt-in change.  Perhaps
> with time, if we hear many users asking this to be the default, we
> will reverse the default value.

I want to be clear about exactly what the new behavior should be.  Since
the patch referred to by "the above adjustment" was faulty and I
followed it with an improvement, I assume "the new behavior that moves
point" refers to the latter patch.  So the user option would specify the
behavior when selecting a region which extends backward from point,
providing a choice between (i) the current behavior (as default), which
leaves point at the position of the click and does not scroll backward
if the region extends above window-start; and (ii) the new behavior,
which moves point to region-beginning, scrolling if the region extends
above window-start (the new behavior is thus the mirror image of the
current behavior when selecting a region which extends forward from
point).  Here is a patch implementing this:

diff --git a/lisp/mouse.el b/lisp/mouse.el
index 8d72753..2f9ff6b 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -540,15 +540,31 @@ mouse-drag-vertical-line
   (interactive "e")
   (mouse-drag-line start-event 'vertical))
 
+(defcustom mouse-select-region-backward nil
+  "Effect of selecting a region extending backward from double click.
+
+Nil means keep point at the position clicked (region end) and
+don't scroll backward when the region extends above the top of
+the window; non-nil means move point to region beginning,
+scrolling when the region extends above the top of the window."
+  :version "26.1"
+  :type '(choice (const :tag "Keep point and don't scroll backward" nil)
+		 (const :tag "Move point and scroll if needed" t)))
+
 (defun mouse-set-point (event &optional promote-to-region)
   "Move point to the position clicked on with the mouse.
 This should be bound to a mouse click event type.
-If PROMOTE-TO-REGION is non-nil and event is a multiple-click,
-select the corresponding element around point."
+If PROMOTE-TO-REGION is non-nil and event is a multiple-click, select
+the corresponding element around point, with the resulting position of
+point determined by `mouse-select-region-backward'."
   (interactive "e\np")
   (mouse-minibuffer-check event)
   (if (and promote-to-region (> (event-click-count event) 1))
-      (mouse-set-region event)
+      (progn
+        (mouse-set-region event)
+        (when mouse-select-region-backward
+          (when (> (posn-point (event-start event)) (region-beginning))
+            (exchange-point-and-mark))))
     ;; Use event-end in case called from mouse-drag-region.
     ;; If EVENT is a click, event-end and event-start give same value.
     (posn-set-point (event-end event))))

But note that, prior to the patch in my previous post, what was under
discussion as the new behavior was different: namely, scrolling if the
region extends above window-start but leaving point at the position of
the click.  This is a sort of compromise between the current behavior
and that in (ii), and it could be a third choice for the user option.
Here is a patch for this alternative:

diff --git a/lisp/mouse.el b/lisp/mouse.el
index 8d72753..19b4804 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -540,15 +540,37 @@ mouse-drag-vertical-line
   (interactive "e")
   (mouse-drag-line start-event 'vertical))
 
+(defcustom mouse-select-region-backward nil
+  "Effect of selecting a region extending backward from double click.
+
+Nil means keep point at the position clicked (region end) and
+don't scroll backward when the region extends above the top of
+the window; `keep' means keep point at region end but scroll when
+the region extends above the top of the window; `move' means move
+point to region beginning, scrolling when the region extends
+above the top of the window."
+  :version "26.1"
+  :type '(choice (const :tag "Keep point and don't scroll backward" nil)
+                 (const :tag "Keep point and scroll if needed" keep)
+		 (const :tag "Move point and scroll if needed" move)))
+
 (defun mouse-set-point (event &optional promote-to-region)
   "Move point to the position clicked on with the mouse.
 This should be bound to a mouse click event type.
-If PROMOTE-TO-REGION is non-nil and event is a multiple-click,
-select the corresponding element around point."
+If PROMOTE-TO-REGION is non-nil and event is a multiple-click, select
+the corresponding element around point, with the resulting position of
+point determined by `mouse-select-region-backward'."
   (interactive "e\np")
   (mouse-minibuffer-check event)
   (if (and promote-to-region (> (event-click-count event) 1))
-      (mouse-set-region event)
+      (progn
+        (mouse-set-region event)
+        (when mouse-select-region-backward
+          (when (> (posn-point (event-start event)) (region-beginning))
+            (exchange-point-and-mark)))
+        (when (eq mouse-select-region-backward 'keep)
+          (sit-for 0)
+          (exchange-point-and-mark)))
     ;; Use event-end in case called from mouse-drag-region.
     ;; If EVENT is a click, event-end and event-start give same value.
     (posn-set-point (event-end event))))

A problem with the `keep' choice is that, when the region is too big for
the window, there is a somewhat jarring flicker due to exchanging point
and mark twice and redisplayin in between, and perhaps even worse, when
scroll-conservatively is 0, the region shown in the window can be
smaller than the text shown before selecting, due to recentering.  But
for smaller regions, the `keep' choice could be a useful option.

Do you have a preference between these two alternatives?  (Perhaps Noam
and Drew wish to chime in here, since they in effect commented only on
the `keep' choice, not the `move' choice.)

Steve Berman