diff options
| author | shipmints | 2025-02-22 05:13:05 -0500 |
|---|---|---|
| committer | Juri Linkov | 2025-03-06 20:37:44 +0200 |
| commit | efd483cf0ecde3b0545a9eb39cc3fa9483fad76c (patch) | |
| tree | b133b0feb7052c057ac1767012bc78884a5745a8 /src | |
| parent | 63cc542b9402ad0a794f4e05790366bd580b8bd1 (diff) | |
| download | emacs-efd483cf0ecde3b0545a9eb39cc3fa9483fad76c.tar.gz emacs-efd483cf0ecde3b0545a9eb39cc3fa9483fad76c.zip | |
mouse-face properties on tab-bar tab captions (bug#76394)
* etc/NEWS: Announce 'tab-bar' 'mouse-face' support.
* src/xdisp.c (note_tab_bar_highlight): Handle mouse-face property.
* lisp/tab-bar.el
(tab-bar-tab-highlight): New face.
(tab-bar-tab-name-format-mouse-face): New function adds the 'mouse-face'
'tab-bar-tab-highlight' to the tab name.
(tab-bar-tab-name-format-functions): Add
'tab-bar-tab-name-format-mouse-face'.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xdisp.c | 131 |
1 files changed, 114 insertions, 17 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index a290664534e..ac654934e54 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -15084,7 +15084,6 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p, | |||
| 15084 | return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0))); | 15084 | return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0))); |
| 15085 | } | 15085 | } |
| 15086 | 15086 | ||
| 15087 | |||
| 15088 | /* Possibly highlight a tab-bar item on frame F when mouse moves to | 15087 | /* Possibly highlight a tab-bar item on frame F when mouse moves to |
| 15089 | tab-bar window-relative coordinates X/Y. Called from | 15088 | tab-bar window-relative coordinates X/Y. Called from |
| 15090 | note_mouse_highlight. */ | 15089 | note_mouse_highlight. */ |
| @@ -15096,8 +15095,7 @@ note_tab_bar_highlight (struct frame *f, int x, int y) | |||
| 15096 | struct window *w = XWINDOW (window); | 15095 | struct window *w = XWINDOW (window); |
| 15097 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); | 15096 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 15098 | int hpos, vpos; | 15097 | int hpos, vpos; |
| 15099 | struct glyph *glyph; | 15098 | struct glyph *glyph = NULL; |
| 15100 | struct glyph_row *row; | ||
| 15101 | int i; | 15099 | int i; |
| 15102 | Lisp_Object enabled_p; | 15100 | Lisp_Object enabled_p; |
| 15103 | int prop_idx; | 15101 | int prop_idx; |
| @@ -15143,25 +15141,124 @@ note_tab_bar_highlight (struct frame *f, int x, int y) | |||
| 15143 | 15141 | ||
| 15144 | /* If tab-bar item is not enabled, don't highlight it. */ | 15142 | /* If tab-bar item is not enabled, don't highlight it. */ |
| 15145 | enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P); | 15143 | enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P); |
| 15144 | |||
| 15146 | if (!NILP (enabled_p) && !NILP (Vmouse_highlight)) | 15145 | if (!NILP (enabled_p) && !NILP (Vmouse_highlight)) |
| 15147 | { | 15146 | { |
| 15148 | /* Compute the x-position of the glyph. In front and past the | 15147 | struct glyph_row *row = NULL; |
| 15149 | image is a space. We include this in the highlighted area. */ | 15148 | struct glyph *row_start_glyph = NULL; |
| 15149 | struct glyph *tmp_glyph; | ||
| 15150 | int total_pixel_width; | ||
| 15151 | Lisp_Object string; | ||
| 15152 | Lisp_Object mouse_face; | ||
| 15153 | int mouse_face_id = -1; | ||
| 15154 | int hpos0, hpos_caption; | ||
| 15155 | |||
| 15150 | row = MATRIX_ROW (w->current_matrix, vpos); | 15156 | row = MATRIX_ROW (w->current_matrix, vpos); |
| 15151 | for (i = x = 0; i < hpos; ++i) | 15157 | /* display_tab_bar does not yet support R2L. */ |
| 15152 | x += row->glyphs[TEXT_AREA][i].pixel_width; | 15158 | eassert (!row->reversed_p); |
| 15159 | row_start_glyph = row->glyphs[TEXT_AREA]; | ||
| 15160 | |||
| 15161 | string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION); | ||
| 15162 | if (STRINGP (string)) | ||
| 15163 | { | ||
| 15164 | /* Compute starting column of the tab-bar-item to adjust col | ||
| 15165 | of the mouse face relative to row_start_glyph. | ||
| 15166 | |||
| 15167 | tab_bar_item_info does not contain the absolute starting | ||
| 15168 | offset of the item. We compute it by looking backwards | ||
| 15169 | until we find a glyph that belongs to a previous tab bar | ||
| 15170 | item, or if this is the first item. */ | ||
| 15171 | hpos0 = hpos + 1; | ||
| 15172 | int tmp_prop_idx; | ||
| 15173 | bool tmp_bool; | ||
| 15174 | for (tmp_glyph = glyph; | ||
| 15175 | tmp_glyph >= row_start_glyph; | ||
| 15176 | tmp_glyph--) | ||
| 15177 | { | ||
| 15178 | if (!tab_bar_item_info (f, tmp_glyph, &tmp_prop_idx, &tmp_bool) | ||
| 15179 | || tmp_prop_idx != prop_idx) | ||
| 15180 | break; /* Just before the beginning of this item. */ | ||
| 15181 | else | ||
| 15182 | --hpos0; | ||
| 15183 | } | ||
| 15153 | 15184 | ||
| 15154 | /* Record this as the current active region. */ | 15185 | /* Offset into the caption vs. the row. */ |
| 15155 | hlinfo->mouse_face_beg_col = hpos; | 15186 | hpos_caption = hpos - hpos0; |
| 15156 | hlinfo->mouse_face_beg_row = vpos; | ||
| 15157 | hlinfo->mouse_face_beg_x = x; | ||
| 15158 | hlinfo->mouse_face_past_end = false; | ||
| 15159 | 15187 | ||
| 15160 | hlinfo->mouse_face_end_col = hpos + 1; | 15188 | mouse_face = Fget_text_property (make_fixnum (hpos_caption), |
| 15161 | hlinfo->mouse_face_end_row = vpos; | 15189 | Qmouse_face, string); |
| 15162 | hlinfo->mouse_face_end_x = x + glyph->pixel_width; | 15190 | if (!NILP (mouse_face)) |
| 15163 | hlinfo->mouse_face_window = window; | 15191 | { |
| 15164 | hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID; | 15192 | mouse_face_id = lookup_named_face (w, f, mouse_face, false); |
| 15193 | if (mouse_face_id < 0) | ||
| 15194 | mouse_face_id = compute_char_face (f, ' ', mouse_face); | ||
| 15195 | draw = DRAW_MOUSE_FACE; | ||
| 15196 | } | ||
| 15197 | } | ||
| 15198 | |||
| 15199 | if (draw == DRAW_MOUSE_FACE) | ||
| 15200 | { | ||
| 15201 | Lisp_Object b, e; | ||
| 15202 | ptrdiff_t begpos, endpos; | ||
| 15203 | int beg_x, end_x; | ||
| 15204 | |||
| 15205 | /* Search for mouse-face boundaries. */ | ||
| 15206 | b = Fprevious_single_property_change (make_fixnum (hpos_caption + 1), | ||
| 15207 | Qmouse_face, string, Qnil); | ||
| 15208 | if (NILP (b)) | ||
| 15209 | begpos = 0; | ||
| 15210 | else | ||
| 15211 | begpos = XFIXNUM (b); | ||
| 15212 | e = Fnext_single_property_change (make_fixnum (begpos), Qmouse_face, string, Qnil); | ||
| 15213 | if (NILP (e)) | ||
| 15214 | endpos = SCHARS (string); | ||
| 15215 | else | ||
| 15216 | endpos = XFIXNUM (e); | ||
| 15217 | |||
| 15218 | /* Compute the starting and ending pixel coordinates */ | ||
| 15219 | for (i = beg_x = 0; | ||
| 15220 | i < hpos0 + begpos; ++i) | ||
| 15221 | beg_x += row->glyphs[TEXT_AREA][i].pixel_width; | ||
| 15222 | for (end_x = 0, | ||
| 15223 | i = hpos0 + begpos; | ||
| 15224 | i < hpos0 + endpos; ++i) | ||
| 15225 | end_x += row->glyphs[TEXT_AREA][i].pixel_width; | ||
| 15226 | |||
| 15227 | if ( EQ (window, hlinfo->mouse_face_window) | ||
| 15228 | && (hlinfo->mouse_face_beg_col <= hpos | ||
| 15229 | && hpos < hlinfo->mouse_face_end_col) | ||
| 15230 | && hlinfo->mouse_face_beg_row == vpos ) | ||
| 15231 | return; | ||
| 15232 | |||
| 15233 | hlinfo->mouse_face_window = window; | ||
| 15234 | hlinfo->mouse_face_face_id = mouse_face_id; | ||
| 15235 | hlinfo->mouse_face_beg_row = vpos; | ||
| 15236 | hlinfo->mouse_face_end_row = vpos; | ||
| 15237 | hlinfo->mouse_face_past_end = false; | ||
| 15238 | hlinfo->mouse_face_beg_col = hpos0 + begpos; | ||
| 15239 | hlinfo->mouse_face_end_col = hpos0 + endpos; | ||
| 15240 | hlinfo->mouse_face_beg_x = beg_x; | ||
| 15241 | hlinfo->mouse_face_end_x = end_x; | ||
| 15242 | } | ||
| 15243 | else | ||
| 15244 | { | ||
| 15245 | /* Compute the x-position of the glyph. In front and past the | ||
| 15246 | image is a space. We include this in the highlighted area. */ | ||
| 15247 | for (i = x = 0; i < hpos; ++i) | ||
| 15248 | x += row->glyphs[TEXT_AREA][i].pixel_width; | ||
| 15249 | total_pixel_width = glyph->pixel_width; | ||
| 15250 | |||
| 15251 | hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID; | ||
| 15252 | hlinfo->mouse_face_beg_col = hpos; | ||
| 15253 | hlinfo->mouse_face_beg_row = vpos; | ||
| 15254 | hlinfo->mouse_face_beg_x = x; | ||
| 15255 | hlinfo->mouse_face_past_end = false; | ||
| 15256 | |||
| 15257 | hlinfo->mouse_face_end_col = hpos + 1; | ||
| 15258 | hlinfo->mouse_face_end_row = vpos; | ||
| 15259 | hlinfo->mouse_face_end_x = x + total_pixel_width; | ||
| 15260 | hlinfo->mouse_face_window = window; | ||
| 15261 | } | ||
| 15165 | 15262 | ||
| 15166 | /* Display it as active. */ | 15263 | /* Display it as active. */ |
| 15167 | show_mouse_face (hlinfo, draw, true); | 15264 | show_mouse_face (hlinfo, draw, true); |