aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2021-10-14 11:57:07 +0300
committerEli Zaretskii2021-10-14 11:57:07 +0300
commit64f9fdc812bb2e1f533ae294355d33396985e469 (patch)
treeb3433e201cd3943f85e38e4584f18003fc9e6cb0 /src
parent9c0128faf7d8de1a017e94595420a16a27321fc1 (diff)
downloademacs-64f9fdc812bb2e1f533ae294355d33396985e469.tar.gz
emacs-64f9fdc812bb2e1f533ae294355d33396985e469.zip
Fix display of cursor in mouse-highlighted face with ':box'
* src/xdisp.c (erase_phys_cursor, show_mouse_face): Adjust phys_cursor.x as needed if the cursor is inside mouse-highlight. (get_cursor_offset_for_mouse_face): New function. * src/dispnew.c (gui_update_window_end): Set 'mouse_face_overwritten_p' if the cursor is in mouse-face, to trigger more thorough redisplay of the cursor. (Bug#50660)
Diffstat (limited to 'src')
-rw-r--r--src/dispnew.c3
-rw-r--r--src/xdisp.c147
2 files changed, 148 insertions, 2 deletions
diff --git a/src/dispnew.c b/src/dispnew.c
index 69c2023fdf3..c3f6d0bfef1 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3848,6 +3848,9 @@ gui_update_window_end (struct window *w, bool cursor_on_p,
3848 w->output_cursor.hpos, w->output_cursor.vpos, 3848 w->output_cursor.hpos, w->output_cursor.vpos,
3849 w->output_cursor.x, w->output_cursor.y); 3849 w->output_cursor.x, w->output_cursor.y);
3850 3850
3851 if (cursor_in_mouse_face_p (w) && cursor_on_p)
3852 mouse_face_overwritten_p = 1;
3853
3851 if (draw_window_fringes (w, true)) 3854 if (draw_window_fringes (w, true))
3852 { 3855 {
3853 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)) 3856 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
diff --git a/src/xdisp.c b/src/xdisp.c
index d8aff5084c4..012c2ad8bf2 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1179,7 +1179,9 @@ static void append_stretch_glyph (struct it *, Lisp_Object,
1179static Lisp_Object get_it_property (struct it *, Lisp_Object); 1179static Lisp_Object get_it_property (struct it *, Lisp_Object);
1180static Lisp_Object calc_line_height_property (struct it *, Lisp_Object, 1180static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
1181 struct font *, int, bool); 1181 struct font *, int, bool);
1182 1182static void get_cursor_offset_for_mouse_face (struct window *w,
1183 struct glyph_row *row,
1184 int *offset);
1183#endif /* HAVE_WINDOW_SYSTEM */ 1185#endif /* HAVE_WINDOW_SYSTEM */
1184 1186
1185static void produce_special_glyphs (struct it *, enum display_element_type); 1187static void produce_special_glyphs (struct it *, enum display_element_type);
@@ -29519,6 +29521,8 @@ produce_image_glyph (struct it *it)
29519 29521
29520 if (face->box != FACE_NO_BOX) 29522 if (face->box != FACE_NO_BOX)
29521 { 29523 {
29524 /* If you change the logic here, please change it in
29525 get_cursor_offset_for_mouse_face as well. */
29522 if (face->box_horizontal_line_width > 0) 29526 if (face->box_horizontal_line_width > 0)
29523 { 29527 {
29524 if (slice.y == 0) 29528 if (slice.y == 0)
@@ -31751,6 +31755,10 @@ erase_phys_cursor (struct window *w)
31751 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); 31755 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
31752 int hpos = w->phys_cursor.hpos; 31756 int hpos = w->phys_cursor.hpos;
31753 int vpos = w->phys_cursor.vpos; 31757 int vpos = w->phys_cursor.vpos;
31758#ifdef HAVE_WINDOW_SYSTEM
31759 int mouse_delta;
31760 int phys_x = w->phys_cursor.x;
31761#endif
31754 bool mouse_face_here_p = false; 31762 bool mouse_face_here_p = false;
31755 struct glyph_matrix *active_glyphs = w->current_matrix; 31763 struct glyph_matrix *active_glyphs = w->current_matrix;
31756 struct glyph_row *cursor_row; 31764 struct glyph_row *cursor_row;
@@ -31820,6 +31828,17 @@ erase_phys_cursor (struct window *w)
31820 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0) 31828 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
31821 mouse_face_here_p = true; 31829 mouse_face_here_p = true;
31822 31830
31831#ifdef HAVE_WINDOW_SYSTEM
31832 /* Adjust the physical cursor's X coordinate if needed. The problem
31833 solved by the code below is outlined in the comment above
31834 'get_cursor_offset_for_mouse_face'. */
31835 if (mouse_face_here_p)
31836 {
31837 get_cursor_offset_for_mouse_face (w, cursor_row, &mouse_delta);
31838 w->phys_cursor.x += mouse_delta;
31839 }
31840#endif
31841
31823 /* Maybe clear the display under the cursor. */ 31842 /* Maybe clear the display under the cursor. */
31824 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR) 31843 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
31825 { 31844 {
@@ -31855,6 +31874,10 @@ erase_phys_cursor (struct window *w)
31855 draw_phys_cursor_glyph (w, cursor_row, hl); 31874 draw_phys_cursor_glyph (w, cursor_row, hl);
31856 31875
31857 mark_cursor_off: 31876 mark_cursor_off:
31877#ifdef HAVE_WINDOW_SYSTEM
31878 /* Restore the original cursor position. */
31879 w->phys_cursor.x = phys_x;
31880#endif
31858 w->phys_cursor_on_p = false; 31881 w->phys_cursor_on_p = false;
31859 w->phys_cursor_type = NO_CURSOR; 31882 w->phys_cursor_type = NO_CURSOR;
31860} 31883}
@@ -32091,6 +32114,9 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
32091 && hlinfo->mouse_face_end_row < w->current_matrix->nrows) 32114 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
32092 { 32115 {
32093 bool phys_cursor_on_p = w->phys_cursor_on_p; 32116 bool phys_cursor_on_p = w->phys_cursor_on_p;
32117#ifdef HAVE_WINDOW_SYSTEM
32118 int mouse_off = 0;
32119#endif
32094 struct glyph_row *row, *first, *last; 32120 struct glyph_row *row, *first, *last;
32095 32121
32096 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row); 32122 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
@@ -32164,6 +32190,15 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
32164 row->mouse_face_p 32190 row->mouse_face_p
32165 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED; 32191 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
32166 } 32192 }
32193#ifdef HAVE_WINDOW_SYSTEM
32194 /* Compute the cursor offset due to mouse-highlight. */
32195 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
32196 /* But not when highlighting a pseudo window, such as
32197 the toolbar, which can't have a cursor anyway. */
32198 && !w->pseudo_window_p
32199 && draw == DRAW_MOUSE_FACE)
32200 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
32201#endif
32167 } 32202 }
32168 32203
32169 /* When we've written over the cursor, arrange for it to 32204 /* When we've written over the cursor, arrange for it to
@@ -32173,6 +32208,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
32173 { 32208 {
32174#ifdef HAVE_WINDOW_SYSTEM 32209#ifdef HAVE_WINDOW_SYSTEM
32175 int hpos = w->phys_cursor.hpos; 32210 int hpos = w->phys_cursor.hpos;
32211 int old_phys_cursor_x = w->phys_cursor.x;
32176 32212
32177 /* When the window is hscrolled, cursor hpos can legitimately be 32213 /* When the window is hscrolled, cursor hpos can legitimately be
32178 out of bounds, but we draw the cursor at the corresponding 32214 out of bounds, but we draw the cursor at the corresponding
@@ -32184,7 +32220,11 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
32184 32220
32185 block_input (); 32221 block_input ();
32186 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos, 32222 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
32187 w->phys_cursor.x, w->phys_cursor.y); 32223 w->phys_cursor.x + mouse_off,
32224 w->phys_cursor.y);
32225 /* Restore the original cursor coordinates, perhaps modified
32226 to account for mouse-highlight. */
32227 w->phys_cursor.x = old_phys_cursor_x;
32188 unblock_input (); 32228 unblock_input ();
32189#endif /* HAVE_WINDOW_SYSTEM */ 32229#endif /* HAVE_WINDOW_SYSTEM */
32190 } 32230 }
@@ -35956,4 +35996,107 @@ cancel_hourglass (void)
35956 } 35996 }
35957} 35997}
35958 35998
35999/* Get the offset due to mouse-highlight to apply before drawing
36000 phys_cursor, and return it in OFFSET. ROW should be the row that
36001 is under mouse face and contains the phys cursor.
36002
36003 This is required because the produce_XXX_glyph series of functions
36004 add the width of the various vertical box lines to the total width
36005 of the glyphs, but that must be updated when the row is put under
36006 mouse face, which can have different box dimensions. */
36007static void
36008get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
36009 int *offset)
36010{
36011 int sum = 0;
36012 /* Return because the mode line can't possibly have a cursor. */
36013 if (row->mode_line_p)
36014 return;
36015
36016 block_input ();
36017
36018 struct frame *f = WINDOW_XFRAME (w);
36019 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36020 struct glyph *start, *end;
36021 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
36022 int hpos = w->phys_cursor.hpos;
36023 end = &row->glyphs[TEXT_AREA][hpos];
36024
36025 if (!row->reversed_p)
36026 {
36027 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
36028 hlinfo->mouse_face_beg_row)
36029 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
36030 else
36031 start = row->glyphs[TEXT_AREA];
36032 }
36033 else
36034 {
36035 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
36036 hlinfo->mouse_face_end_row)
36037 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
36038 else
36039 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
36040 }
36041
36042 /* Calculate the offset to correct phys_cursor x if we are
36043 drawing the cursor inside mouse-face highlighted text. */
36044
36045 for (; row->reversed_p ? start >= end : start <= end;
36046 row->reversed_p ? --start : ++start)
36047 {
36048 struct glyph *g = start;
36049 struct face *mouse = mouse_face;
36050 struct face *regular_face = FACE_FROM_ID (f, g->face_id);
36051
36052 bool do_left_box_p = g->left_box_line_p;
36053 bool do_right_box_p = g->right_box_line_p;
36054
36055 /* This is required because we test some parameters
36056 of the image slice before applying the box in
36057 produce_image_glyph. */
36058
36059 if (g->type == IMAGE_GLYPH)
36060 {
36061 if (!row->reversed_p)
36062 {
36063 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
36064 g->u.img_id);
36065 do_left_box_p = g->left_box_line_p &&
36066 g->slice.img.x == 0;
36067 do_right_box_p = g->right_box_line_p &&
36068 g->slice.img.x + g->slice.img.width == img->width;
36069 }
36070 else
36071 {
36072 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
36073 g->u.img_id);
36074 do_left_box_p = g->left_box_line_p &&
36075 g->slice.img.x + g->slice.img.width == img->width;
36076 do_right_box_p = g->right_box_line_p &&
36077 g->slice.img.x == 0;
36078 }
36079 }
36080
36081 /* If the glyph has a left box line, subtract it from the offset. */
36082 if (do_left_box_p)
36083 sum -= max (0, regular_face->box_vertical_line_width);
36084 /* Likewise with the right box line, as there may be a
36085 box there as well. */
36086 if (do_right_box_p)
36087 sum -= max (0, regular_face->box_vertical_line_width);
36088 /* Now add the line widths from the new face. */
36089 if (g->left_box_line_p)
36090 sum += max (0, mouse->box_vertical_line_width);
36091 if (g->right_box_line_p)
36092 sum += max (0, mouse->box_vertical_line_width);
36093 }
36094
36095 if (row->reversed_p)
36096 sum = -sum;
36097
36098 *offset = sum;
36099
36100 unblock_input ();
36101}
35959#endif /* HAVE_WINDOW_SYSTEM */ 36102#endif /* HAVE_WINDOW_SYSTEM */