unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Moritz Maxeiner <mm@ucw.sh>
To: Eli Zaretskii <eliz@gnu.org>, Po Lu <luangruo@yahoo.com>
Cc: emacs-devel@gnu.org
Subject: Re: Moving point after character when clicking latter half of it
Date: Tue, 11 Jul 2023 20:01:59 +0200	[thread overview]
Message-ID: <21946289.EfDdHjke4D@anduin> (raw)
In-Reply-To: <87wmz6bnlr.fsf@yahoo.com>

[-- Attachment #1: Type: text/plain, Size: 3525 bytes --]

On Tuesday 11 July 2023 15:10:24 CEST Po Lu wrote:
> Eli Zaretskii <eliz@gnu.org> writes:
> > I'm not sure this is TRT.  In particular, it sounds like the change
> > you made in xterm.c also overrides the Y coordinate condition? that
> > doesn't sound right to me.  Po Lu, WDYT about this?
> > 
> > The other changes LGTM, thanks.
> 
> This part of the patch
> 
> >    if (frame != dpyinfo->last_mouse_glyph_frame
> >    
> >        || event->x < r->x || event->x >= r->x + r->width
> > 
> > -      || event->y < r->y || event->y >= r->y + r->height)
> > +      || event->y < r->y || event->y >= r->y + r->height
> > +      || mouse_click_prefer_closest_char && EQ (track_mouse,
> > Qdrag_tracking))
> appears to special case a value of `track_mouse', and unconditionally
> report mouse movement upon such a value being set, without considering
> if the mouse pointer has moved to a position within the glyph that could
> lead to a new position being reported.

True, though it is still conditional on the optional feature being enabled 
(both mouse_click_prefer_closest_char and drag_tracking, which mouse.el sets, 
need to be true). That being said I tried before to have this only be reported 
when the mouse crosses halfway point (without modifying the glyph itself) but 
that didn't really work.

> This is not only wrong (since
> Emacs shouldn't report mouse events differently even if `track_mouse' is
> some other non-nil value), but is also inefficient, as setting
> mouse_moved unnecessarily will result in an excessive number of mouse
> motion events being reported.

I'm not clear on why that would make it wrong (as in incorrect semantics). 
It's definitely inefficient (though I've not noticed the overhead in practice), 
which is why I asked if there's a more elegant solution.

> 
> I don't think we should disable the optimizations here entirely;
> instead, it should be just as effective to save only the half of the
> glyph containing the mouse pointer inside `remember_mouse_glyph' when
> `mouse_click_prefer_closest_char' is true.

Which this is, thank you very much for pointing that out. I've changed that 
part of the patch accordingly, though this does unfortunately mean that a new 
function is required, due to multiple places setting the glyph rectangle as it 
relates to dragging.


> 
> > +  DEFVAR_BOOL ("mouse-click-prefer-closest-char",
> > mouse_click_prefer_closest_char, +	       doc: /* Non-nil means mouse
> > click prefers the closest glyph as point. +When this is non-nil, clicking
> > inside a glyph picks up the next glyph if the click +is closer to it then
> > half the width of the clicked glyph.  */);
> > +  mouse_click_prefer_closest_char = false;
> 
> Since this affects much more than just mouse clicks, shouldn't the
> variable be named something else?  How about naming the variable
> `mouse-prefer-closest-glyph', and using the following doc string
> instead:
> 
>   Non-nil means mouse position lists are reported relative to the glyph
>   closest to their coordinates.
> 
>   When non-nil, mouse position lists will be reported with their
>   `posn-point' set to the position of the glyph closest to the mouse
>   pointer, instead of the glyph immediately under.

I've included those changes.

> 
> Also, shouldn't the Lisp reference manual mention this variable?  In
> (elisp)Accessing Mouse, for example.

Assuming this version of the implementation meets muster I will work on the 
etc/NEWS entry and can look into adding something to (elisp)Accessing Mouse, 
as well.

[-- Attachment #2: emacs-29-move_it_in_display_line_to-nextglyphafterhalf-poc-0.5.patch --]
[-- Type: text/x-patch, Size: 3956 bytes --]

diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index 054683d7cf6..2ed904f178f 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -231,6 +231,7 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
 	     (inverse-video display boolean)
 	     (visible-bell display boolean)
 	     (no-redraw-on-reenter display boolean)
+	     (mouse-prefer-closest-glyph display boolean)
 
              ;; doc.c
              (text-quoting-style display
diff --git a/src/dispnew.c b/src/dispnew.c
index 65d9cf9b4e1..669cd5f4d33 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -5611,6 +5611,15 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
      argument is ZV to prevent move_it_in_display_line from matching
      based on buffer positions.  */
   move_it_in_display_line (&it, ZV, to_x, MOVE_TO_X);
+  if (mouse_prefer_closest_glyph)
+    {
+      int next_x = it.current_x + it.pixel_width;
+      int before_dx = to_x - it.current_x;
+      int after_dx = next_x - to_x;
+      if (before_dx > after_dx)
+        move_it_in_display_line (&it, ZV, next_x, MOVE_TO_X);
+    }
+
   bidi_unshelve_cache (itdata, 0);
 
   Fset_buffer (old_current_buffer);
@@ -6788,6 +6797,15 @@ predicates which report frame's specific UI-related capabilities.  */);
   DEFVAR_BOOL ("cursor-in-echo-area", cursor_in_echo_area,
 	       doc: /* Non-nil means put cursor in minibuffer, at end of any message there.  */);
 
+  DEFVAR_BOOL ("mouse-prefer-closest-glyph", mouse_prefer_closest_glyph,
+	       doc: /*  Non-nil means mouse position lists are reported relative
+to the glyph closest to their coordinates.
+
+ When non-nil, mouse position lists will be reported with their
+`posn-point' set to the position of the glyph closest to the mouse
+pointer, instead of the glyph immediately under.  */);
+  mouse_prefer_closest_glyph = false;
+
   DEFVAR_LISP ("glyph-table", Vglyph_table,
 	       doc: /* Table defining how to output a glyph code to the frame.
 If not nil, this is a vector indexed by glyph code to define the glyph.
diff --git a/src/xterm.c b/src/xterm.c
index 5840b15bcb7..b460603068c 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -14161,6 +14161,20 @@ x_construct_mouse_click (struct input_event *result,
   return Qnil;
 }
 
+/* Function to bisect `glyph` into left and right halves, then
+   replace it with the half in which `x` is.  */
+
+static void
+x_vertical_bisect_glyph(XRectangle *glyph, int x)
+{
+  int halfwidth = glyph->width / 2;
+  glyph->width = halfwidth;
+
+  int bisection = glyph->x + halfwidth;
+  if (x > bisection)
+    glyph->x = bisection;
+}
+
 /* Function to report a mouse movement to the mainstream Emacs code.
    The input handler calls this.
 
@@ -14218,6 +14232,8 @@ x_note_mouse_movement (struct frame *frame, const XMotionEvent *event,
       note_mouse_highlight (frame, event->x, event->y);
       /* Remember which glyph we're now on.  */
       remember_mouse_glyph (frame, event->x, event->y, r);
+      if (mouse_prefer_closest_glyph)
+        x_vertical_bisect_glyph(r, event->x);
       dpyinfo->last_mouse_glyph_frame = frame;
       return true;
     }
@@ -14382,6 +14398,8 @@ x_fast_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
 	  remember_mouse_glyph (f1, win_x, win_y,
 				&dpyinfo->last_mouse_glyph);
 	  dpyinfo->last_mouse_glyph_frame = f1;
+	  if (mouse_prefer_closest_glyph)
+	    x_vertical_bisect_glyph(&dpyinfo->last_mouse_glyph, win_x);
 
 	  *bar_window = Qnil;
 	  *part = scroll_bar_nowhere;
@@ -14733,6 +14751,8 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
 	    dpyinfo = FRAME_DISPLAY_INFO (f1);
 	    remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
 	    dpyinfo->last_mouse_glyph_frame = f1;
+	    if (mouse_prefer_closest_glyph)
+	      x_vertical_bisect_glyph(&dpyinfo->last_mouse_glyph, win_x);
 
 	    *bar_window = Qnil;
 	    *part = 0;

  reply	other threads:[~2023-07-11 18:01 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-08 21:01 Moving point after character when clicking latter half of it Moritz Maxeiner
2023-07-09  6:35 ` Eli Zaretskii
2023-07-09 12:44   ` Moritz Maxeiner
2023-07-09 13:23     ` Eli Zaretskii
2023-07-09 13:51       ` Moritz Maxeiner
2023-07-09 14:14         ` Eli Zaretskii
2023-07-09 21:47           ` Moritz Maxeiner
2023-07-10 12:46             ` Eli Zaretskii
2023-07-10 14:43               ` [External] : " Drew Adams
2023-07-10 20:02               ` Moritz Maxeiner
2023-07-11 12:29                 ` Eli Zaretskii
2023-07-11 13:10                   ` Po Lu
2023-07-11 18:01                     ` Moritz Maxeiner [this message]
2023-07-12  0:52                       ` Po Lu
2023-07-12 19:58                         ` Moritz Maxeiner
2023-07-12 21:17                           ` Yuan Fu
2023-07-12 21:36                             ` Moritz Maxeiner
2023-07-12 22:08                               ` Yuan Fu
2023-07-13  5:27                             ` Eli Zaretskii
2023-07-13 23:25                               ` Yuan Fu
2023-07-13  0:31                           ` Po Lu
2023-07-13  8:47                           ` Eli Zaretskii
2023-07-21 19:04                             ` Moritz Maxeiner
2023-07-21 23:57                               ` Po Lu
2023-07-22  5:41                                 ` Eli Zaretskii
2023-07-22 10:07                                   ` Moritz Maxeiner
2023-07-22 11:31                                     ` Po Lu
2023-07-22 12:51                                     ` Eli Zaretskii
2023-07-22 15:28                                       ` Moritz Maxeiner
2023-07-22 15:51                                         ` Eli Zaretskii
2023-07-22 15:59                                           ` Moritz Maxeiner
2023-07-22 16:34                                             ` Eli Zaretskii
2023-07-22 19:10                                             ` Yuan Fu
2023-07-09 13:58       ` Yuri Khan
2023-07-09 12:40 ` Benjamin Riefenstahl
2023-07-09 12:47   ` Moritz Maxeiner
2023-07-09 13:37     ` Benjamin Riefenstahl
2023-07-09 15:15   ` [External] : " Drew Adams
2023-07-09 15:33     ` Moritz Maxeiner
2023-07-09 16:06       ` Drew Adams
2023-07-09 16:21       ` Brian Cully via Emacs development discussions.
2023-07-09 18:01         ` Jens Schmidt
2023-07-09 16:43       ` [External] : " Eli Zaretskii
2023-07-12 18:21     ` Benjamin Riefenstahl
2023-07-12 18:32       ` Eli Zaretskii
     [not found] ` <12248204.O9o76ZdvQC@anduin>
     [not found]   ` <87ilac2kla.fsf@yahoo.com>
2023-07-22 14:48     ` Moritz Maxeiner
2023-07-22 15:26       ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=21946289.EfDdHjke4D@anduin \
    --to=mm@ucw.sh \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    --cc=luangruo@yahoo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).