From: Eli Zaretskii Date: Sat, 21 Oct 2023 10:53:21 +0000 (+0300) Subject: Fix mouse clicks on links under 'global-display-line-numbers-mode' X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=e57b19b4007336c8f85f0dae0d4125d096d3d1f4;p=emacs.git Fix mouse clicks on links under 'global-display-line-numbers-mode' * 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) --- diff --git a/src/indent.c b/src/indent.c index eda85f2e94d..7d34d3638d9 100644 --- a/src/indent.c +++ b/src/indent.c @@ -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); diff --git a/src/keyboard.c b/src/keyboard.c index 76dec637cb1..07af12d8d44 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -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)), diff --git a/src/lisp.h b/src/lisp.h index 39aa51531fe..df6cf1df544 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -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);