diff options
| author | Eli Zaretskii | 2021-10-14 11:57:07 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2021-10-14 11:57:07 +0300 |
| commit | 64f9fdc812bb2e1f533ae294355d33396985e469 (patch) | |
| tree | b3433e201cd3943f85e38e4584f18003fc9e6cb0 /src | |
| parent | 9c0128faf7d8de1a017e94595420a16a27321fc1 (diff) | |
| download | emacs-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.c | 3 | ||||
| -rw-r--r-- | src/xdisp.c | 147 |
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, | |||
| 1179 | static Lisp_Object get_it_property (struct it *, Lisp_Object); | 1179 | static Lisp_Object get_it_property (struct it *, Lisp_Object); |
| 1180 | static Lisp_Object calc_line_height_property (struct it *, Lisp_Object, | 1180 | static Lisp_Object calc_line_height_property (struct it *, Lisp_Object, |
| 1181 | struct font *, int, bool); | 1181 | struct font *, int, bool); |
| 1182 | 1182 | static 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 | ||
| 1185 | static void produce_special_glyphs (struct it *, enum display_element_type); | 1187 | static 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. */ | ||
| 36007 | static void | ||
| 36008 | get_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 */ |