commit 844b8949a71f180d395a237c768b22d91cf91ded (HEAD, refs/remotes/origin/master) Author: Stefan Monnier Date: Tue Apr 13 23:55:47 2021 -0400 * src/xdisp.c (wset_update_mode_line): Move from `src/window.c` Move that function next to its siblings. Also simplify it, since after careful analysis it is now clear that the frame's title's update is already handled elsewhere (in `prepare_menu_bars` and `redisplay_window`) so we just need to make sure the `redisplay` bit is set. * src/window.c (wset_update_mode_line): Move to `src/xdisp.c`. * src/window.h (wset_update_mode_line): Declare. diff --git a/src/window.c b/src/window.c index 4d5c7e763e..caf9df6c13 100644 --- a/src/window.c +++ b/src/window.c @@ -215,20 +215,6 @@ wset_combination (struct window *w, bool horflag, Lisp_Object val) w->horizontal = horflag; } -static void -wset_update_mode_line (struct window *w) -{ - /* If this window is the selected window on its frame, set the - global variable update_mode_lines, so that gui_consider_frame_title - will consider this frame's title for redisplay. */ - Lisp_Object fselected_window = XFRAME (WINDOW_FRAME (w))->selected_window; - - if (WINDOWP (fselected_window) && XWINDOW (fselected_window) == w) - update_mode_lines = 42; - else - w->update_mode_line = true; -} - /* True if leaf window W doesn't reflect the actual state of displayed buffer due to its text or overlays change. */ diff --git a/src/window.h b/src/window.h index b6f88e8f55..2400c422c1 100644 --- a/src/window.h +++ b/src/window.h @@ -1141,6 +1141,7 @@ extern void wset_redisplay (struct window *w); extern void fset_redisplay (struct frame *f); extern void bset_redisplay (struct buffer *b); extern void bset_update_mode_line (struct buffer *b); +extern void wset_update_mode_line (struct window *w); /* Call this to tell redisplay to look for other windows than selected-window that need to be redisplayed. Calling one of the *set_redisplay functions above already does it, so it's only needed in unusual cases. */ diff --git a/src/xdisp.c b/src/xdisp.c index 8f7180381b..9e5516602b 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -869,6 +869,18 @@ bset_update_mode_line (struct buffer *b) b->text->redisplay = true; } +void +wset_update_mode_line (struct window *w) +{ + w->update_mode_line = true; + /* When a window's mode line needs to be updated, the window's frame's + title may also need to be updated, but we don't need to worry about it + here. Instead, `gui_consider_frame_title` is automatically called + whenever w->update_mode_line is set for that frame's selected window. + But for this to work reliably, we have to make sure the window + is considered, so we have to mark it for redisplay. */ + wset_redisplay (w); } + DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay, Sset_buffer_redisplay, 4, 4, 0, doc: /* Mark the current buffer for redisplay. commit 839a9e74e0263f4e75a0c34df39c2e0a57c49438 Author: Stefan Monnier Date: Tue Apr 13 23:34:35 2021 -0400 * lisp/nxml/xmltok.el (xmltok-defregexp): Don't quote lambda diff --git a/lisp/nxml/xmltok.el b/lisp/nxml/xmltok.el index 8f89598a5a..9824eebbd8 100644 --- a/lisp/nxml/xmltok.el +++ b/lisp/nxml/xmltok.el @@ -324,8 +324,8 @@ and VALUE-END, otherwise a STRING giving the value." (setq strs (cons (car arg) strs)) (setq names (cons (cdr arg) names))) (setq args (cdr args)))) - (cons (apply 'concat (nreverse strs)) - (apply 'append (nreverse names)))))) + (cons (apply #'concat (nreverse strs)) + (apply #'append (nreverse names)))))) (eval-when-compile ;; Make a symbolic group named NAME from the regexp R. @@ -338,7 +338,7 @@ and VALUE-END, otherwise a STRING giving the value." (cons (concat "\\(" (car ,sym) "\\)") (cons ',name (cdr ,sym))))))) (defun xmltok-p (&rest r) (xmltok+ "\\(?:" - (apply 'xmltok+ r) + (apply #'xmltok+ r) "\\)")) ;; Get the group index of ELEM in a LIST of symbols. @@ -372,22 +372,23 @@ and VALUE-END, otherwise a STRING giving the value." (defmacro xmltok-defregexp (sym r) `(defalias ',sym (let ((r ,r)) - `(macro lambda (action &optional group-name) - (cond ((eq action 'regexp) - ,(car r)) - ((or (eq action 'start) (eq action 'beginning)) - (list 'match-beginning (xmltok-get-index group-name - ',(cdr r)))) - ((eq action 'end) - (list 'match-end (xmltok-get-index group-name - ',(cdr r)))) - ((eq action 'string) - (list 'match-string - (xmltok-get-index group-name ',(cdr r)))) - ((eq action 'string-no-properties) - (list 'match-string-no-properties - (xmltok-get-index group-name ',(cdr r)))) - (t (error "Invalid action: %s" action)))))))) + `(macro + . ,(lambda (action &optional group-name) + (cond ((eq action 'regexp) + (car r)) + ((or (eq action 'start) (eq action 'beginning)) + (list 'match-beginning (xmltok-get-index group-name + (cdr r)))) + ((eq action 'end) + (list 'match-end (xmltok-get-index group-name + (cdr r)))) + ((eq action 'string) + (list 'match-string + (xmltok-get-index group-name (cdr r)))) + ((eq action 'string-no-properties) + (list 'match-string-no-properties + (xmltok-get-index group-name (cdr r)))) + (t (error "Invalid action: %s" action))))))))) (eval-when-compile @@ -878,7 +879,7 @@ and VALUE-END, otherwise a STRING giving the value." (cons " " value-parts))))) (< (point) end)))) (when well-formed - (aset att 5 (apply 'concat (nreverse value-parts)))) + (aset att 5 (apply #'concat (nreverse value-parts)))) (aset att 6 (nreverse refs)))) (defun xmltok-scan-after-amp (entity-handler) @@ -1333,7 +1334,7 @@ If LIMIT is non-nil, then do not consider characters beyond LIMIT." t)))) (if (not well-formed) nil - (apply 'concat + (apply #'concat (nreverse (cons (buffer-substring-no-properties start lim) value-parts)))))) @@ -1358,7 +1359,7 @@ If LIMIT is non-nil, then do not consider characters beyond LIMIT." (defun xmltok-require-next-token (&rest types) (xmltok-next-prolog-token) - (apply 'xmltok-require-token types)) + (apply #'xmltok-require-token types)) (defun xmltok-require-token (&rest types) ;; XXX Generate a more helpful error message commit 86daa721bb287652a70162c8dcdf8d9d37013ac7 Author: Stefan Monnier Date: Tue Apr 13 23:28:04 2021 -0400 * lisp/emacs-lisp/eieio-core.el (list-of): Don't quote lambda diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el index e7727fd3fc..2923dffd95 100644 --- a/lisp/emacs-lisp/eieio-core.el +++ b/lisp/emacs-lisp/eieio-core.el @@ -169,7 +169,7 @@ Return nil if that option doesn't exist." (and (recordp obj) (eieio--class-p (eieio--object-class obj)))) -(define-obsolete-function-alias 'object-p 'eieio-object-p "25.1") +(define-obsolete-function-alias 'object-p #'eieio-object-p "25.1") (defun class-abstract-p (class) "Return non-nil if CLASS is abstract. @@ -242,9 +242,9 @@ use \\='%s or turn off `eieio-backward-compatibility' instead" cname) (cl-deftype list-of (elem-type) `(and list - (satisfies (lambda (list) - (cl-every (lambda (elem) (cl-typep elem ',elem-type)) - list))))) + (satisfies ,(lambda (list) + (cl-every (lambda (elem) (cl-typep elem elem-type)) + list))))) (defun eieio-make-class-predicate (class) @@ -787,7 +787,7 @@ Fills in OBJ's SLOT with its default value." (cond ;; Is it a function call? If so, evaluate it. ((eieio-eval-default-p val) - (eval val)) + (eval val t)) ;;;; check for quoted things, and unquote them ;;((and (consp val) (eq (car val) 'quote)) ;; (car (cdr val))) @@ -1029,7 +1029,7 @@ method invocation orders of the involved classes." (eieio--class-precedence-c3 class)))))) (define-obsolete-function-alias - 'class-precedence-list 'eieio--class-precedence-list "24.4") + 'class-precedence-list #'eieio--class-precedence-list "24.4") ;;; Here are some special types of errors commit 468a00f380ec46d57fec73c0dbb90779963be4fe Author: Filipp Gunbin Date: Tue Apr 13 20:07:20 2021 +0300 * doc/lispref/keymaps.texi (Translation Keymaps): Fix small misprint diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index dabf985018..cbc94d8c1b 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -1686,7 +1686,7 @@ presence of such a binding can still prevent translation from taking place. For example, let us return to our VT100 example above and add a binding for @kbd{C-c @key{ESC}} to the global map; now when the user hits @kbd{C-c @key{PF1}} Emacs will fail to decode @kbd{C-c @key{ESC} O P} into @kbd{C-c -@key{PF1}} because it will stop reading keys right after @kbd{C-x @key{ESC}}, +@key{PF1}} because it will stop reading keys right after @kbd{C-c @key{ESC}}, leaving @kbd{O P} for later. This is in case the user really hit @kbd{C-c @key{ESC}}, in which case Emacs should not sit there waiting for the next key to decide whether the user really pressed @kbd{@key{ESC}} or @kbd{@key{PF1}}. commit 9738b5b93bb5ec3d8f2d360a334bd8a184637101 Author: Filipp Gunbin Date: Tue Apr 13 19:54:17 2021 +0300 * doc/lispref/processes.texi: Fix small misprint diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index b3246494a2..6786ac28f9 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -1325,7 +1325,7 @@ the numeric ID of the foreground process group of @var{process}; it returns @code{nil} if Emacs can be certain that this is not so. The value is @code{t} if Emacs cannot tell whether this is true. This function signals an error if @var{process} is a network, serial, or -pipe connection, or is the subprocess is not active. +pipe connection, or if the subprocess is not active. @end defun @node Signals to Processes commit 17ff8c3e5a9dec2640ca95d295110c81ebb59a2c Author: Eric Abrahamsen Date: Sat Mar 13 14:25:47 2021 -0800 Improvements to message-syntax-checks docs and options * doc/misc/message.texi: Move the manual entry from the "News Headers" section to the "Message Headers" section, as it is generally applicable, not just to News. * lisp/gnus/message.el (message-syntax-checks): Add an explicit alist type specifying the valid options; point to the manual for more information. diff --git a/doc/misc/message.texi b/doc/misc/message.texi index 1497c710e4..d2353e6cec 100644 --- a/doc/misc/message.texi +++ b/doc/misc/message.texi @@ -1792,8 +1792,89 @@ member list with elements @code{CC} and @code{To}, then @code{message-carefully-insert-headers} will not insert a @code{To} header when the message is already @code{CC}ed to the recipient. +@item message-syntax-checks +@vindex message-syntax-checks +Controls what syntax checks should not be performed on outgoing posts. +To disable checking of long signatures, for instance, add + +@lisp +(signature . disabled) +@end lisp + +to this list. + +Valid checks are: + +@table @code +@item approved +@cindex approved +Check whether the article has an @code{Approved} header, which is +something only moderators should include. +@item continuation-headers +Check whether there are continuation header lines that don't begin with +whitespace. +@item control-chars +Check for invalid characters. +@item empty +Check whether the article is empty. +@item existing-newsgroups +Check whether the newsgroups mentioned in the @code{Newsgroups} and +@code{Followup-To} headers exist. +@item from +Check whether the @code{From} header seems nice. +@item illegible-text +Check whether there is any non-printable character in the body. +@item invisible-text +Check whether there is any invisible text in the buffer. +@item long-header-lines +Check for too long header lines. +@item long-lines +@cindex long lines +Check for too long lines in the body. +@item message-id +Check whether the @code{Message-ID} looks syntactically ok. +@item multiple-headers +Check for the existence of multiple equal headers. +@item new-text +Check whether there is any new text in the messages. +@item newsgroups +Check whether the @code{Newsgroups} header exists and is not empty. +@item quoting-style +Check whether text follows last quoted portion. +@item repeated-newsgroups +Check whether the @code{Newsgroups} and @code{Followup-To} headers +contains repeated group names. +@item reply-to +Check whether the @code{Reply-To} header looks ok. +@item sender +@cindex Sender +Insert a new @code{Sender} header if the @code{From} header looks odd. +@item sendsys +@cindex sendsys +Check for the existence of version and sendsys commands. +@item shoot +Check whether the domain part of the @code{Message-ID} header looks ok. +@item shorten-followup-to +Check whether to add a @code{Followup-To} header to shorten the number +of groups to post to. +@item signature +Check the length of the signature. +@item size +Check for excessive size. +@item subject +Check whether the @code{Subject} header exists and is not empty. +@item subject-cmsg +Check the subject for commands. +@item valid-newsgroups +Check whether the @code{Newsgroups} and @code{Followup-To} headers +are valid syntactically. @end table +All these conditions are checked by default, except for @code{sender} +for which the check is disabled by default if +@code{message-insert-canlock} is non-@code{nil} (@pxref{Canceling News}). + +@end table @node Mail Headers @section Mail Headers @@ -2072,88 +2153,6 @@ Other variables for customizing outgoing news articles: @table @code -@item message-syntax-checks -@vindex message-syntax-checks -Controls what syntax checks should not be performed on outgoing posts. -To disable checking of long signatures, for instance, add - -@lisp -(signature . disabled) -@end lisp - -to this list. - -Valid checks are: - -@table @code -@item approved -@cindex approved -Check whether the article has an @code{Approved} header, which is -something only moderators should include. -@item continuation-headers -Check whether there are continuation header lines that don't begin with -whitespace. -@item control-chars -Check for invalid characters. -@item empty -Check whether the article is empty. -@item existing-newsgroups -Check whether the newsgroups mentioned in the @code{Newsgroups} and -@code{Followup-To} headers exist. -@item from -Check whether the @code{From} header seems nice. -@item illegible-text -Check whether there is any non-printable character in the body. -@item invisible-text -Check whether there is any invisible text in the buffer. -@item long-header-lines -Check for too long header lines. -@item long-lines -@cindex long lines -Check for too long lines in the body. -@item message-id -Check whether the @code{Message-ID} looks syntactically ok. -@item multiple-headers -Check for the existence of multiple equal headers. -@item new-text -Check whether there is any new text in the messages. -@item newsgroups -Check whether the @code{Newsgroups} header exists and is not empty. -@item quoting-style -Check whether text follows last quoted portion. -@item repeated-newsgroups -Check whether the @code{Newsgroups} and @code{Followup-To} headers -contains repeated group names. -@item reply-to -Check whether the @code{Reply-To} header looks ok. -@item sender -@cindex Sender -Insert a new @code{Sender} header if the @code{From} header looks odd. -@item sendsys -@cindex sendsys -Check for the existence of version and sendsys commands. -@item shoot -Check whether the domain part of the @code{Message-ID} header looks ok. -@item shorten-followup-to -Check whether to add a @code{Followup-To} header to shorten the number -of groups to post to. -@item signature -Check the length of the signature. -@item size -Check for excessive size. -@item subject -Check whether the @code{Subject} header exists and is not empty. -@item subject-cmsg -Check the subject for commands. -@item valid-newsgroups -Check whether the @code{Newsgroups} and @code{Followup-To} headers -are valid syntactically. -@end table - -All these conditions are checked by default, except for @code{sender} -for which the check is disabled by default if -@code{message-insert-canlock} is non-@code{nil} (@pxref{Canceling News}). - @item message-ignored-news-headers @vindex message-ignored-news-headers Regexp of headers to be removed before posting. The default is@* diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index f3b830cf84..02db38725a 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -187,22 +187,26 @@ Otherwise, most addresses look like `angles', but they look like (defcustom message-syntax-checks (if message-insert-canlock '((sender . disabled)) nil) - ;; Guess this one shouldn't be easy to customize... "Controls what syntax checks should not be performed on outgoing posts. To disable checking of long signatures, for instance, add `(signature . disabled)' to this list. Don't touch this variable unless you really know what you're doing. -Checks include `approved', `bogus-recipient', `continuation-headers', -`control-chars', `empty', `existing-newsgroups', `from', `illegible-text', -`invisible-text', `long-header-lines', `long-lines', `message-id', -`multiple-headers', `new-text', `newsgroups', `quoting-style', -`repeated-newsgroups', `reply-to', `sender', `sendsys', `shoot', -`shorten-followup-to', `signature', `size', `subject', `subject-cmsg' -and `valid-newsgroups'." - :group 'message-news - :type '(repeat sexp)) ; Fixme: improve this +See the Message manual for the meanings of the valid syntax check +types." + :group 'message-headers + :link '(custom-manual "(message)Message Headers") + :type '(alist + :key-type symbol + :value-type (const disabled) + :options (approved bogus-recipient continuation-headers + control-chars empty existing-newsgroups from illegible-text + invisible-text long-header-lines long-lines message-id + multiple-headers new-text newgroups quoting-style + repeated-newsgroups reply-to sender sendsys shoot + shorten-followup-to signature size subject subject-cmsg + valid-newsgroups))) (defcustom message-required-headers '((optional . References) From) commit 1db460784e90b7c78c5d541640a4d520f9b406b1 Author: Stefan Monnier Date: Tue Apr 13 09:59:23 2021 -0400 * lisp/textmodes/two-column.el: Address FIXME (2C-associate-buffer): Move minibuffer interactive to the `interactive` spec. diff --git a/lisp/textmodes/two-column.el b/lisp/textmodes/two-column.el index 6c3bacc647..5a3a64ad79 100644 --- a/lisp/textmodes/two-column.el +++ b/lisp/textmodes/two-column.el @@ -319,16 +319,17 @@ first and the associated buffer to its right." ;;;###autoload -(defun 2C-associate-buffer () - "Associate another buffer with this one in two-column minor mode. +(defun 2C-associate-buffer (buffer) + "Associate another BUFFER with this one in two-column minor mode. Can also be used to associate a just previously visited file, by accepting the proposed default buffer. \(See \\[describe-mode] .)" - (interactive) + (interactive + (list (or (2C-other) + (read-buffer "Associate buffer: " (other-buffer))))) (let ((b1 (current-buffer)) - (b2 (or (2C-other) - (read-buffer "Associate buffer: " (other-buffer))))) + (b2 buffer)) (setq 2C-mode nil) (with-current-buffer b2 (and (2C-other) commit cf605d56f99a4e109dc27e548551c5cb5c171b7b Author: Stefan Monnier Date: Tue Apr 13 09:47:46 2021 -0400 * lisp/textmodes/paragraphs.el (multiple-lines): Remove mistaken declaration (forward-paragraph): Remove unused var `multiple-lines`. diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el index 31e91c7303..59b15e82a8 100644 --- a/lisp/textmodes/paragraphs.el +++ b/lisp/textmodes/paragraphs.el @@ -202,8 +202,6 @@ This is desirable in modes where blank lines are the paragraph delimiters." (put 'paragraph-ignore-fill-prefix 'safe-local-variable #'booleanp) ;; Silence the compiler. -(defvar multiple-lines) - (defun forward-paragraph (&optional arg) "Move forward to end of paragraph. With argument ARG, do it ARG times; @@ -262,13 +260,13 @@ Returns the count of paragraphs left to move." ;; Search back for line that starts or separates paragraphs. (if (if fill-prefix-regexp ;; There is a fill prefix; it overrides parstart. - (let (multiple-lines) + (let () ;; multiple-lines (while (and (progn (beginning-of-line) (not (bobp))) (progn (move-to-left-margin) (not (looking-at parsep))) (looking-at fill-prefix-regexp)) - (unless (= (point) start) - (setq multiple-lines t)) + ;; (unless (= (point) start) + ;; (setq multiple-lines t)) (forward-line -1)) (move-to-left-margin) ;; This deleted code caused a long hanging-indent line commit 1667253fec963e2ffb2bb36db67564533cf92787 Author: Eli Zaretskii Date: Tue Apr 13 16:40:42 2021 +0300 Resurrect mouse-highlight of close buttons on tab-bar * src/w32term.c (w32_draw_image_relief): Support tab-bar drawing with relief as xterm.c does. * src/xdisp.c (handle_tab_bar_click): Access the mouse-highlight info. Call show_mouse_face to show the button in the pressed or the released state, according to value of DOWN_P. (note_tab_bar_highlight): Function added back. (note_mouse_highlight): Call note_tab_bar_highlight when the mouse pointer is in the tab-bar window. (show_mouse_face): Return immediately if mouse_face_window is not set up in HLINFO. This avoids rare assertion violations. diff --git a/src/w32term.c b/src/w32term.c index 0ee805a852..361cf33c02 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -2031,8 +2031,11 @@ w32_draw_image_relief (struct glyph_string *s) if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED) { - thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief - : DEFAULT_TOOL_BAR_BUTTON_RELIEF; + thick = (tab_bar_button_relief < 0 + ? DEFAULT_TAB_BAR_BUTTON_RELIEF + : (tool_bar_button_relief < 0 + ? DEFAULT_TOOL_BAR_BUTTON_RELIEF + : min (tool_bar_button_relief, 1000000))); raised_p = s->hl == DRAW_IMAGE_RAISED; } else @@ -2045,6 +2048,19 @@ w32_draw_image_relief (struct glyph_string *s) y1 = y + s->slice.height - 1; extra_x = extra_y = 0; + if (s->face->id == TAB_BAR_FACE_ID) + { + if (CONSP (Vtab_bar_button_margin) + && FIXNUMP (XCAR (Vtab_bar_button_margin)) + && FIXNUMP (XCDR (Vtab_bar_button_margin))) + { + extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)); + extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)); + } + else if (FIXNUMP (Vtab_bar_button_margin)) + extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin); + } + if (s->face->id == TOOL_BAR_FACE_ID) { if (CONSP (Vtool_bar_button_margin) diff --git a/src/xdisp.c b/src/xdisp.c index 50d9040057..8f7180381b 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -13682,6 +13682,7 @@ void handle_tab_bar_click (struct frame *f, int x, int y, bool down_p, int modifiers) { + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); struct window *w = XWINDOW (f->tab_bar_window); int hpos, vpos, prop_idx; bool close_p; @@ -13703,13 +13704,22 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p, return; if (down_p) - f->last_tab_bar_item = prop_idx; /* record the pressed tab */ + { + /* Show the clicked button in pressed state. */ + if (!NILP (Vmouse_highlight)) + show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN); + f->last_tab_bar_item = prop_idx; /* record the pressed tab */ + } else { Lisp_Object key, frame; struct input_event event; EVENT_INIT (event); + /* Show item in released state. */ + if (!NILP (Vmouse_highlight)) + show_mouse_face (hlinfo, DRAW_IMAGE_RAISED); + key = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY); XSETFRAME (frame, f); @@ -13722,6 +13732,97 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p, } } + +/* Possibly highlight a tab-bar item on frame F when mouse moves to + tab-bar window-relative coordinates X/Y. Called from + note_mouse_highlight. */ + +static void +note_tab_bar_highlight (struct frame *f, int x, int y) +{ + Lisp_Object window = f->tab_bar_window; + struct window *w = XWINDOW (window); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); + int hpos, vpos; + struct glyph *glyph; + struct glyph_row *row; + int i; + Lisp_Object enabled_p; + int prop_idx; + bool close_p; + enum draw_glyphs_face draw = DRAW_IMAGE_RAISED; + int rc; + + /* Function note_mouse_highlight is called with negative X/Y + values when mouse moves outside of the frame. */ + if (x <= 0 || y <= 0) + { + clear_mouse_face (hlinfo); + return; + } + + rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p); + if (rc < 0) + { + /* Not on tab-bar item. */ + clear_mouse_face (hlinfo); + return; + } + else if (rc == 0) + /* On same tab-bar item as before. */ + goto set_help_echo; + + clear_mouse_face (hlinfo); + + bool mouse_down_p = false; +#ifndef HAVE_NS + /* Mouse is down, but on different tab-bar item? */ + Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); + mouse_down_p = (gui_mouse_grabbed (dpyinfo) + && f == dpyinfo->last_mouse_frame); + + if (mouse_down_p && f->last_tab_bar_item != prop_idx) + return; +#endif + draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; + + /* If tab-bar item is not enabled, don't highlight it. */ + enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P); + if (!NILP (enabled_p) && !NILP (Vmouse_highlight)) + { + /* Compute the x-position of the glyph. In front and past the + image is a space. We include this in the highlighted area. */ + row = MATRIX_ROW (w->current_matrix, vpos); + for (i = x = 0; i < hpos; ++i) + x += row->glyphs[TEXT_AREA][i].pixel_width; + + /* Record this as the current active region. */ + hlinfo->mouse_face_beg_col = hpos; + hlinfo->mouse_face_beg_row = vpos; + hlinfo->mouse_face_beg_x = x; + hlinfo->mouse_face_past_end = false; + + hlinfo->mouse_face_end_col = hpos + 1; + hlinfo->mouse_face_end_row = vpos; + hlinfo->mouse_face_end_x = x + glyph->pixel_width; + hlinfo->mouse_face_window = window; + hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID; + + /* Display it as active. */ + show_mouse_face (hlinfo, draw); + } + + set_help_echo: + + /* Set help_echo_string to a help string to display for this tab-bar item. + XTread_socket does the rest. */ + help_echo_object = help_echo_window = Qnil; + help_echo_pos = -1; + help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP); + if (NILP (help_echo_string)) + help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION); +} + #endif /* HAVE_WINDOW_SYSTEM */ /* Find the tab-bar item at X coordinate and return its information. */ @@ -31860,6 +31961,11 @@ draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row, static void show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) { + /* Don't bother doing anything if the mouse-face window is not set + up. */ + if (!WINDOWP (hlinfo->mouse_face_window)) + return; + struct window *w = XWINDOW (hlinfo->mouse_face_window); struct frame *f = XFRAME (WINDOW_FRAME (w)); @@ -33414,9 +33520,13 @@ note_mouse_highlight (struct frame *f, int x, int y) frame_to_window_pixel_xy (w, &x, &y); #if defined (HAVE_WINDOW_SYSTEM) - /* We don't highlight tab-bar buttons. */ + /* Handle tab-bar window differently since it doesn't display a + buffer. */ if (EQ (window, f->tab_bar_window)) - return; + { + note_tab_bar_highlight (f, x, y); + return; + } #endif #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)