]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix mouse clicks on links under 'global-display-line-numbers-mode'
authorEli Zaretskii <eliz@gnu.org>
Sat, 21 Oct 2023 10:53:21 +0000 (13:53 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sat, 21 Oct 2023 10:53:21 +0000 (13:53 +0300)
* src/indent.c (line_number_display_width): No longer static.
* src/lisp.h (line_number_display_width): Add prototype.
* src/keyboard.c (save_line_number_display_width)
(line_number_mode_hscroll): New functions.
(make_lispy_event): Call 'save_line_number_display_width' and
'line_number_mode_hscroll' to avoid interpreting up-event as drag
event when redisplay scrolls the text horizontally between the
down- and up-event to account for the changed width of the
line-number display.  (Bug#66655)

src/indent.c
src/keyboard.c
src/lisp.h

index eda85f2e94ddb5d5369dc3393ddb2df3c8b6ac35..7d34d3638d933b52a989bff6f773fa4d38953c6b 100644 (file)
@@ -2031,7 +2031,7 @@ vmotion (ptrdiff_t from, ptrdiff_t from_byte,
 }
 
 /* Return the width taken by line-number display in window W.  */
-static void
+void
 line_number_display_width (struct window *w, int *width, int *pixel_width)
 {
   if (NILP (Vdisplay_line_numbers))
@@ -2101,7 +2101,7 @@ numbers on display.  */)
 {
   int width, pixel_width;
   struct window *w = XWINDOW (selected_window);
-  line_number_display_width (XWINDOW (selected_window), &width, &pixel_width);
+  line_number_display_width (w, &width, &pixel_width);
   if (EQ (pixelwise, Qcolumns))
     {
       struct frame *f = XFRAME (w->frame);
index 76dec637cb12eb23dcbf4b5b774462f0cc2e8c93..07af12d8d444112fa21f421945acee759d2fa42c 100644 (file)
@@ -5531,6 +5531,10 @@ static Lisp_Object button_down_location;
    the down mouse event.  */
 static Lisp_Object frame_relative_event_pos;
 
+/* The line-number display width, in columns, at the time of most
+   recent down mouse event.  */
+static int down_mouse_line_number_width;
+
 /* Information about the most recent up-going button event:  Which
    button, what location, and what time.  */
 
@@ -5927,6 +5931,54 @@ coords_in_tab_bar_window (struct frame *f, int x, int y)
 
 #endif /* HAVE_WINDOW_SYSTEM */
 
+static void
+save_line_number_display_width (struct input_event *event)
+{
+  struct window *w;
+  int pixel_width;
+
+  if (WINDOWP (event->frame_or_window))
+    w = XWINDOW (event->frame_or_window);
+  else if (FRAMEP (event->frame_or_window))
+    w = XWINDOW (XFRAME (event->frame_or_window)->selected_window);
+  line_number_display_width (w, &down_mouse_line_number_width, &pixel_width);
+}
+
+/* Return non-zero if the change of position from START_POS to END_POS
+   is likely to be the effect of horizontal scrolling due to a change
+   in line-number width produced by redisplay between two mouse
+   events, like mouse-down followed by mouse-up, at those positions.
+   This is used to decide whether to converts mouse-down followed by
+   mouse-up event into a mouse-drag event.  */
+static bool
+line_number_mode_hscroll (Lisp_Object start_pos, Lisp_Object end_pos)
+{
+  if (!EQ (Fcar (start_pos), Fcar (end_pos)) /* different window */
+      || list_length (start_pos) < 7        /* no COL/ROW info */
+      || list_length (end_pos) < 7)
+    return false;
+
+  Lisp_Object start_col_row = Fnth (make_fixnum (6), start_pos);
+  Lisp_Object end_col_row = Fnth (make_fixnum (6), end_pos);
+  Lisp_Object window = Fcar (end_pos);
+  int col_width, pixel_width, start_col, end_col;
+  struct window *w;
+  if (!WINDOW_VALID_P (window))
+    {
+      if (WINDOW_LIVE_P (window))
+       window = XFRAME (window)->selected_window;
+      else
+       window = selected_window;
+    }
+  w = XWINDOW (window);
+  line_number_display_width (w, &col_width, &pixel_width);
+  start_col = Fcar (start_col_row);
+  end_col = Fcar (end_col_row);
+  return start_col == end_col
+        && down_mouse_line_number_width >= 0
+        && col_width != down_mouse_line_number_width;
+}
+
 /* Given a struct input_event, build the lisp event which represents
    it.  If EVENT is 0, build a mouse movement event from the mouse
    movement buffer, which should have a movement event in it.
@@ -6329,6 +6381,8 @@ make_lispy_event (struct input_event *event)
            *start_pos_ptr = Fcopy_alist (position);
            frame_relative_event_pos = Fcons (event->x, event->y);
            ignore_mouse_drag_p = false;
+           /* Squirrel away the line-number width, if any.  */
+           save_line_number_display_width (event);
          }
 
        /* Now we're releasing a button - check the coordinates to
@@ -6374,12 +6428,18 @@ make_lispy_event (struct input_event *event)
                          it's probably OK to ignore it as well.  */
                       && (EQ (Fcar (Fcdr (start_pos)),
                               Fcar (Fcdr (position))) /* Same buffer pos */
+                          /* Redisplay hscrolled text between down- and
+                              up-events due to display-line-numbers-mode.  */
+                          || line_number_mode_hscroll (start_pos, position)
                           || !EQ (Fcar (start_pos),
                                   Fcar (position))))) /* Different window */
+
                  {
                    /* Mouse has moved enough.  */
                    button_down_time = 0;
                    click_or_drag_modifier = drag_modifier;
+                   /* Reset the value for future clicks.  */
+                   down_mouse_line_number_width = -1;
                  }
                else if (((!EQ (Fcar (start_pos), Fcar (position)))
                          || (!EQ (Fcar (Fcdr (start_pos)),
index 39aa51531fe08400898317980f2b8f938e23611c..df6cf1df544a85b842f722b2cfbc07b52f16bee3 100644 (file)
@@ -4883,6 +4883,7 @@ extern void keys_of_keyboard (void);
 
 /* Defined in indent.c.  */
 extern ptrdiff_t current_column (void);
+extern void line_number_display_width (struct window *, int *, int *);
 extern void invalidate_current_column (void);
 extern bool indented_beyond_p (ptrdiff_t, ptrdiff_t, EMACS_INT);
 extern void syms_of_indent (void);