aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuri Linkov2019-09-15 23:52:22 +0300
committerJuri Linkov2019-09-15 23:52:22 +0300
commit6474abc36359a438338e5d6186dbeaf24f200387 (patch)
tree1d7a4c74483031759169d66a3b12aa722635240c
parent8d30e1bce3c1bddf85272fa31b7d314ed421d29e (diff)
downloademacs-6474abc36359a438338e5d6186dbeaf24f200387.tar.gz
emacs-6474abc36359a438338e5d6186dbeaf24f200387.zip
Use images for new/close buttons in tab-bar and tab-line.
* etc/images/tabs/new.xpm: * etc/images/tabs/close.xpm: New files. * lisp/tab-bar.el (tab-bar-separator): New face. (tab-bar-separator, tab-bar-button-new, tab-bar-button-close): Use display property with images in default values. * lisp/tab-line.el (tab-line-button-new, tab-line-button-close): Use display property with images in default values. * src/xdisp.c (tab_bar_item_info): Add new arg close_p and set it to the value of property `close' at charpos. (get_tab_bar_item): Add new arg close_p. (handle_tab_bar_click): Add ctrl_modifier when close_p is non-nil. (Fdump_tab_bar_row): Fix crash for non-X builds.
-rw-r--r--etc/images/tabs/README8
-rw-r--r--etc/images/tabs/close.xpm16
-rw-r--r--etc/images/tabs/new.xpm16
-rw-r--r--lisp/tab-bar.el157
-rw-r--r--lisp/tab-line.el129
-rw-r--r--src/xdisp.c35
6 files changed, 220 insertions, 141 deletions
diff --git a/etc/images/tabs/README b/etc/images/tabs/README
new file mode 100644
index 00000000000..1e9f4e5b595
--- /dev/null
+++ b/etc/images/tabs/README
@@ -0,0 +1,8 @@
1This directory contains icons for the Tabs user interface.
2
3COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
4
5Files: close.xpm new.xpm
6Author: Juri Linkov <juri@linkov.net>
7Copyright (C) 2019 Free Software Foundation, Inc.
8License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/tabs/close.xpm b/etc/images/tabs/close.xpm
new file mode 100644
index 00000000000..48f063fa43b
--- /dev/null
+++ b/etc/images/tabs/close.xpm
@@ -0,0 +1,16 @@
1/* XPM */
2static char * close_xpm[] = {
3"9 9 4 1",
4" c None",
5". c #CCCCCC",
6"+ c #000000",
7"@ c #808080",
8" ..... ",
9" ....... ",
10"..+@.@+..",
11"..@+@+@..",
12"...@+@...",
13"..@+@+@..",
14"..+@.@+..",
15" ....... ",
16" ..... "};
diff --git a/etc/images/tabs/new.xpm b/etc/images/tabs/new.xpm
new file mode 100644
index 00000000000..e10a8ef238b
--- /dev/null
+++ b/etc/images/tabs/new.xpm
@@ -0,0 +1,16 @@
1/* XPM */
2static char * new_xpm[] = {
3"9 9 4 1",
4" c None",
5". c #BFBFBF",
6"+ c #808080",
7"@ c #000000",
8".........",
9"....+....",
10"....@....",
11"....@....",
12".+@@@@@+.",
13"....@....",
14"....@....",
15"....+....",
16"........."};
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 57be4e09a8f..c15eb2979c4 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -47,37 +47,45 @@
47 :version "27.1") 47 :version "27.1")
48 48
49(defface tab-bar 49(defface tab-bar
50 '((default 50 '((((type x w32 ns) (class color))
51 :box (:line-width 1 :style released-button) 51 :height 1.1
52 :foreground "black" 52 :background "grey85"
53 :background "white") 53 :foreground "black")
54 (((type x w32 ns) (class color))
55 :background "grey75")
56 (((type x) (class mono)) 54 (((type x) (class mono))
57 :background "grey")) 55 :background "grey")
56 (t
57 :inverse-video t))
58 "Tab bar face." 58 "Tab bar face."
59 :version "27.1" 59 :version "27.1"
60 :group 'tab-bar-faces) 60 :group 'tab-bar-faces)
61 61
62(defface tab-bar-tab 62(defface tab-bar-tab
63 '((default 63 '((((class color) (min-colors 88))
64 :inherit tab-bar-tab-inactive) 64 :box (:line-width 1 :style released-button))
65 (t 65 (t
66 :background "grey75")) 66 :inverse-video nil))
67 "Tab bar face for selected tab." 67 "Tab bar face for selected tab."
68 :version "27.1" 68 :version "27.1"
69 :group 'tab-bar-faces) 69 :group 'tab-bar-faces)
70 70
71(defface tab-bar-tab-inactive 71(defface tab-bar-tab-inactive
72 '((((class color) (min-colors 88)) 72 '((default
73 :box (:line-width -15 :style pressed-button) 73 :inherit tab-bar-tab)
74 :background "grey60") 74 (((class color) (min-colors 88))
75 :background "grey75")
75 (t 76 (t
76 :inherit highlight)) 77 :inverse-video t))
77 "Tab bar face for non-selected tab." 78 "Tab bar face for non-selected tab."
78 :version "27.1" 79 :version "27.1"
79 :group 'tab-bar-faces) 80 :group 'tab-bar-faces)
80 81
82(defface tab-bar-separator
83 '((t
84 :inverse-video nil))
85 "Tab bar face for separator."
86 :version "27.1"
87 :group 'tab-bar-faces)
88
81 89
82(define-minor-mode tab-bar-mode 90(define-minor-mode tab-bar-mode
83 "Toggle the tab bar in all graphical frames (Tab Bar mode)." 91 "Toggle the tab bar in all graphical frames (Tab Bar mode)."
@@ -99,7 +107,7 @@
99 (global-set-key [(control shift tab)] 'tab-bar-switch-to-prev-tab) 107 (global-set-key [(control shift tab)] 'tab-bar-switch-to-prev-tab)
100 (global-set-key [(control tab)] 'tab-bar-switch-to-next-tab))) 108 (global-set-key [(control tab)] 'tab-bar-switch-to-next-tab)))
101 109
102(defun tab-bar-mouse (event) 110(defun tab-bar-handle-mouse (event)
103 "Text-mode emulation of switching tabs on the tab-bar. 111 "Text-mode emulation of switching tabs on the tab-bar.
104This command is used when you click the mouse in the tab-bar 112This command is used when you click the mouse in the tab-bar
105on a console which has no window system but does have a mouse." 113on a console which has no window system but does have a mouse."
@@ -113,9 +121,11 @@ on a console which has no window system but does have a mouse."
113 (lambda (_key binding) 121 (lambda (_key binding)
114 (when (eq (car-safe binding) 'menu-item) 122 (when (eq (car-safe binding) 'menu-item)
115 (when (> (+ column (length (nth 1 binding))) x-position) 123 (when (> (+ column (length (nth 1 binding))) x-position)
116 (call-interactively (nth 2 binding)) 124 ;; TODO: handle close
125 (unless (get-text-property (- x-position column) 'close (nth 1 binding))
126 (call-interactively (nth 2 binding)))
117 (throw 'done t)) 127 (throw 'done t))
118 (setq column (+ column (length (nth 1 binding)) 1)))) 128 (setq column (+ column (length (nth 1 binding))))))
119 keymap)) 129 keymap))
120 ;; Clicking anywhere outside existing tabs will add a new tab 130 ;; Clicking anywhere outside existing tabs will add a new tab
121 (tab-bar-add-tab))))) 131 (tab-bar-add-tab)))))
@@ -149,9 +159,30 @@ Its main job is to show tabs in the tab bar."
149 (puthash key tab-bar-map tab-bar-keymap-cache))))) 159 (puthash key tab-bar-map tab-bar-keymap-cache)))))
150 160
151 161
152(defvar tab-bar-separator " ") 162(defvar tab-bar-separator
153(defvar tab-bar-tab-name-add nil) 163 (propertize " " 'face 'tab-bar-separator))
154(defvar tab-bar-tab-name-close nil) 164
165(defvar tab-bar-button-new
166 (propertize " + "
167 'display `(image :type xpm
168 :file ,(expand-file-name
169 "images/tabs/new.xpm"
170 data-directory)
171 :margin (2 . 0)
172 :ascent center))
173 "Button for creating a new tab.")
174
175(defvar tab-bar-button-close
176 (propertize "x"
177 'display `(image :type xpm
178 :file ,(expand-file-name
179 "images/tabs/close.xpm"
180 data-directory)
181 :margin (2 . 0)
182 :ascent center)
183 'close t
184 :help "Click to close tab")
185 "Button for closing the clicked tab.")
155 186
156(defun tab-bar-tab-name () 187(defun tab-bar-tab-name ()
157 "Generate tab name in the context of the selected frame." 188 "Generate tab name in the context of the selected frame."
@@ -172,54 +203,44 @@ Return its existing value or a new value."
172 203
173(defun tab-bar-make-keymap-1 () 204(defun tab-bar-make-keymap-1 ()
174 "Generate an actual keymap from `tab-bar-map', without caching." 205 "Generate an actual keymap from `tab-bar-map', without caching."
175 ;; Can't check for char-displayable-p in defvar
176 ;; because this file is preloaded.
177 (unless tab-bar-tab-name-add
178 (setq tab-bar-tab-name-add
179 (if (char-displayable-p ?âž•) "âž•" "[+]")))
180 (unless tab-bar-tab-name-close
181 (setq tab-bar-tab-name-close
182 ;; Need to add space after Unicode char on terminals
183 ;; to avoid clobbering next char by wide Unicode char.
184 (if (char-displayable-p ?⮿) (if window-system "⮿" "⮿ ") "[x]")))
185 (let ((i 0)) 206 (let ((i 0))
186 (append 207 (append
187 '(keymap (mouse-1 . tab-bar-mouse)) 208 '(keymap (mouse-1 . tab-bar-handle-mouse))
188 (mapcan 209 (mapcan
189 (lambda (tab) 210 (lambda (tab)
190 (setq i (1+ i)) 211 (setq i (1+ i))
191 (list (cond 212 (append
192 ((eq (car tab) 'current-tab) 213 (cond
193 `(current-tab 214 ((eq (car tab) 'current-tab)
194 menu-item 215 `((current-tab
195 ,(propertize (cdr (assq 'name tab)) 'face 'tab-bar-tab) 216 menu-item
196 ignore 217 ,(propertize (concat (cdr (assq 'name tab))
197 :help "Current tab")) 218 (or tab-bar-button-close ""))
198 (t 219 'face 'tab-bar-tab)
199 `(,(intern (format "tab-%i" i)) 220 ignore
200 menu-item 221 :help "Current tab")))
201 ,(propertize (cdr (assq 'name tab)) 'face 'tab-bar-tab-inactive) 222 (t
202 ,(lambda () 223 `((,(intern (format "tab-%i" i))
203 (interactive) 224 menu-item
204 (tab-bar-select-tab tab)) 225 ,(propertize (concat (cdr (assq 'name tab))
205 :help "Click to visit tab"))) 226 (or tab-bar-button-close ""))
206 `(,(intern (format "close-tab-%i" i)) 227 'face 'tab-bar-tab-inactive)
207 menu-item 228 ,(lambda ()
208 ,(concat (propertize tab-bar-tab-name-close 229 (interactive)
209 'face (if (eq (car tab) 'current-tab) 230 (tab-bar-select-tab tab))
210 'tab-bar-tab 231 :help "Click to visit tab"))))
211 'tab-bar-tab-inactive)) 232 `((,(if (eq (car tab) 'current-tab) 'C-current-tab (intern (format "C-tab-%i" i)))
212 tab-bar-separator) 233 menu-item ""
213 ,(lambda () 234 ,(lambda ()
214 (interactive) 235 (interactive)
215 (tab-bar-close-tab tab)) 236 (tab-bar-close-tab tab))))
216 :help "Click to close tab"))) 237 (when (and (stringp tab-bar-separator)
238 (> (length tab-bar-separator) 0))
239 `((,(intern (format "sep-%i" i)) menu-item ,tab-bar-separator ignore)))))
217 (tab-bar-tabs)) 240 (tab-bar-tabs))
218 `((add-tab menu-item 241 (when tab-bar-button-new
219 ,(propertize tab-bar-tab-name-add 242 `((add-tab menu-item ,tab-bar-button-new tab-bar-add-tab
220 'face 'tab-bar-tab-inactive) 243 :help "New tab"))))))
221 tab-bar-add-tab
222 :help "Click to add tab")))))
223 244
224 245
225(defun tab-bar-read-tab-name (prompt) 246(defun tab-bar-read-tab-name (prompt)
@@ -279,16 +300,16 @@ Return its existing value or a new value."
279 (setq tabs (cdr tabs))) 300 (setq tabs (cdr tabs)))
280 (force-window-update)))) 301 (force-window-update))))
281 302
282(defun tab-bar-switch-to-prev-tab () 303(defun tab-bar-switch-to-prev-tab (&optional _arg)
283 "Switch to the previous tab." 304 "Switch to ARGth previous tab."
284 (interactive) 305 (interactive "p")
285 (let ((prev-tab (tab-bar-find-prev-tab))) 306 (let ((prev-tab (tab-bar-find-prev-tab)))
286 (when prev-tab 307 (when prev-tab
287 (tab-bar-select-tab (car prev-tab))))) 308 (tab-bar-select-tab (car prev-tab)))))
288 309
289(defun tab-bar-switch-to-next-tab () 310(defun tab-bar-switch-to-next-tab (&optional _arg)
290 "Switch to the next tab." 311 "Switch to ARGth next tab."
291 (interactive) 312 (interactive "p")
292 (let* ((tabs (tab-bar-tabs)) 313 (let* ((tabs (tab-bar-tabs))
293 (prev-tab (tab-bar-find-prev-tab tabs))) 314 (prev-tab (tab-bar-find-prev-tab tabs)))
294 (if prev-tab 315 (if prev-tab
diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 8ade53611f3..6b1ce03d26e 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -42,48 +42,51 @@
42 :version "27.1") 42 :version "27.1")
43 43
44(defface tab-line 44(defface tab-line
45 '((default :inherit header-line)) 45 '((((type x w32 ns) (class color))
46 :background "grey85"
47 :foreground "black")
48 (((type x) (class mono))
49 :background "grey")
50 (t
51 :inverse-video t))
46 "Tab line face." 52 "Tab line face."
47 :version "27.1" 53 :version "27.1"
48 :group 'tab-line-faces) 54 :group 'tab-line-faces)
49 55
50(defface tab-line-highlight
51 '((default :inherit tab-line-tab))
52 "Tab line face for highlighting."
53 :version "27.1"
54 :group 'tab-line-faces)
55
56(defface tab-line-close-highlight
57 '((t :foreground "red"))
58 "Tab line face for highlighting."
59 :version "27.1"
60 :group 'tab-line-faces)
61
62(defface tab-line-tab 56(defface tab-line-tab
63 '((((class color) (min-colors 88)) 57 '((((class color) (min-colors 88))
64 :box (:line-width -1 :style pressed-button) 58 :box (:line-width 1 :style released-button)
65 :background "white" :foreground "black") 59 :background "grey85")
66 (t 60 (t
67 :inverse-video t)) 61 :inverse-video nil))
68 "Tab line face for selected tab." 62 "Tab line face for selected tab."
69 :version "27.1" 63 :version "27.1"
70 :group 'tab-line-faces) 64 :group 'tab-line-faces)
71 65
72(defface tab-line-tab-inactive 66(defface tab-line-tab-inactive
73 '((default 67 '((default
74 :inherit tab-line) 68 :inherit tab-line-tab)
75 (((class color) (min-colors 88) (background light)) 69 (((class color) (min-colors 88))
76 :weight light 70 :background "grey75")
77 :box (:line-width -1 :color "grey75" :style released-button) 71 (t
78 :foreground "grey20" :background "grey90") 72 :inverse-video t))
79 (((class color) (min-colors 88) (background dark) )
80 :weight light
81 :box (:line-width -1 :color "grey40" :style released-button)
82 :foreground "grey80" :background "grey30"))
83 "Tab line face for non-selected tabs." 73 "Tab line face for non-selected tabs."
84 :version "27.1" 74 :version "27.1"
85 :group 'tab-line-faces) 75 :group 'tab-line-faces)
86 76
77(defface tab-line-highlight
78 '((default :inherit tab-line-tab))
79 "Tab line face for highlighting."
80 :version "27.1"
81 :group 'tab-line-faces)
82
83(defface tab-line-close-highlight
84 '((t :foreground "red"))
85 "Tab line face for highlighting."
86 :version "27.1"
87 :group 'tab-line-faces)
88
89
87(defvar tab-line-tab-map 90(defvar tab-line-tab-map
88 (let ((map (make-sparse-keymap))) 91 (let ((map (make-sparse-keymap)))
89 (define-key map [tab-line mouse-1] 'tab-line-select-tab) 92 (define-key map [tab-line mouse-1] 'tab-line-select-tab)
@@ -112,15 +115,37 @@
112 map) 115 map)
113 "Local keymap to close `tab-line-mode' window tabs.") 116 "Local keymap to close `tab-line-mode' window tabs.")
114 117
118
115(defvar tab-line-separator " ") 119(defvar tab-line-separator " ")
120
116(defvar tab-line-tab-name-ellipsis 121(defvar tab-line-tab-name-ellipsis
117 (if (char-displayable-p ?…) "…" "...")) 122 (if (char-displayable-p ?…) "…" "..."))
118(defvar tab-line-tab-name-add 123
119 (if (char-displayable-p ?âž•) "âž•" "[+]")) 124(defvar tab-line-button-new
120(defvar tab-line-tab-name-close 125 (propertize " + "
121 ;; Need to add space after Unicode char on terminals 126 'display `(image :type xpm
122 ;; to avoid clobbering next char by wide Unicode char. 127 :file ,(expand-file-name
123 (if (char-displayable-p ?⮿) (if window-system "⮿" "⮿ ") "[x]")) 128 "images/tabs/new.xpm"
129 data-directory)
130 :margin (2 . 0)
131 :ascent center)
132 'keymap tab-line-add-map
133 'mouse-face 'tab-line-highlight
134 'help-echo "Click to add tab")
135 "Button for creating a new tab.")
136
137(defvar tab-line-button-close
138 (propertize "x"
139 'display `(image :type xpm
140 :file ,(expand-file-name
141 "images/tabs/close.xpm"
142 data-directory)
143 :margin (2 . 0)
144 :ascent center)
145 'keymap tab-line-tab-close-map
146 'mouse-face 'tab-line-close-highlight
147 'help-echo "Click to close tab")
148 "Button for closing the clicked tab.")
124 149
125 150
126(defun tab-line-tab-name (buffer &optional buffers) 151(defun tab-line-tab-name (buffer &optional buffers)
@@ -171,39 +196,25 @@ Reduce tab width proportionally to space taken by other tabs."
171 (append 196 (append
172 (mapcar 197 (mapcar
173 (lambda (b) 198 (lambda (b)
174 (format "%s%s%s" 199 (concat
175 tab-line-separator 200 (or tab-line-separator "")
176 (apply 'propertize (tab-line-tab-name b buffer-tabs) 201 (apply 'propertize (concat (propertize
177 `( 202 (tab-line-tab-name b buffer-tabs)
178 buffer ,b 203 'keymap tab-line-tab-map)
179 face ,(if (eq b buffer) 204 tab-line-button-close)
180 'tab-line-tab 205 `(
181 'tab-line-tab-inactive) 206 buffer ,b
182 mouse-face tab-line-highlight 207 face ,(if (eq b buffer)
183 keymap ,tab-line-tab-map)) 208 'tab-line-tab
184 (apply 'propertize tab-line-tab-name-close 209 'tab-line-tab-inactive)
185 `( 210 mouse-face tab-line-highlight))))
186 help-echo "Click to close tab"
187 buffer ,b
188 face ,(if (eq b buffer)
189 'tab-line-tab
190 'tab-line-tab-inactive)
191 mouse-face tab-line-close-highlight
192 keymap ,tab-line-tab-close-map))))
193 buffer-tabs) 211 buffer-tabs)
194 (list (format "%s%s" 212 (list (concat tab-line-separator tab-line-button-new)))))
195 tab-line-separator
196 (apply 'propertize tab-line-tab-name-add
197 `(
198 help-echo "Click to add tab"
199 face tab-line-tab-inactive
200 mouse-face tab-line-highlight
201 keymap ,tab-line-add-map)))))))
202 213
203 214
204(defun tab-line-add-tab (&optional e) 215(defun tab-line-add-tab (&optional e)
205 (interactive "e") 216 (interactive "e")
206 (if window-system 217 (if window-system ; (display-popup-menus-p)
207 (mouse-buffer-menu e) ; like (buffer-menu-open) 218 (mouse-buffer-menu e) ; like (buffer-menu-open)
208 ;; tty menu doesn't support mouse clicks, so use tmm 219 ;; tty menu doesn't support mouse clicks, so use tmm
209 (tmm-prompt (mouse-buffer-menu-keymap)))) 220 (tmm-prompt (mouse-buffer-menu-keymap))))
diff --git a/src/xdisp.c b/src/xdisp.c
index e2a4df1c008..f4386884184 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12666,7 +12666,6 @@ display_tab_bar (struct window *w)
12666 struct it it; 12666 struct it it;
12667 Lisp_Object items; 12667 Lisp_Object items;
12668 int i; 12668 int i;
12669 bool has_menu_bar_p = FRAME_MENU_BAR_LINES (f) > 0;
12670 12669
12671 /* Don't do all this for graphical frames. */ 12670 /* Don't do all this for graphical frames. */
12672#ifdef HAVE_NTGUI 12671#ifdef HAVE_NTGUI
@@ -12685,7 +12684,7 @@ display_tab_bar (struct window *w)
12685 12684
12686#if defined (USE_X_TOOLKIT) || defined (USE_GTK) 12685#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
12687 eassert (!FRAME_WINDOW_P (f)); 12686 eassert (!FRAME_WINDOW_P (f));
12688 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + (has_menu_bar_p ? 1 : 0), TAB_BAR_FACE_ID); 12687 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0), TAB_BAR_FACE_ID);
12689 it.first_visible_x = 0; 12688 it.first_visible_x = 0;
12690 it.last_visible_x = FRAME_PIXEL_WIDTH (f); 12689 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
12691#elif defined (HAVE_X_WINDOWS) /* X without toolkit. */ 12690#elif defined (HAVE_X_WINDOWS) /* X without toolkit. */
@@ -12695,7 +12694,7 @@ display_tab_bar (struct window *w)
12695 dummy window tab_bar_window. */ 12694 dummy window tab_bar_window. */
12696 struct window *tab_w; 12695 struct window *tab_w;
12697 tab_w = XWINDOW (f->tab_bar_window); 12696 tab_w = XWINDOW (f->tab_bar_window);
12698 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows + (has_menu_bar_p ? 1 : 0), 12697 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
12699 TAB_BAR_FACE_ID); 12698 TAB_BAR_FACE_ID);
12700 it.first_visible_x = 0; 12699 it.first_visible_x = 0;
12701 it.last_visible_x = FRAME_PIXEL_WIDTH (f); 12700 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
@@ -12705,7 +12704,7 @@ display_tab_bar (struct window *w)
12705 { 12704 {
12706 /* This is a TTY frame, i.e. character hpos/vpos are used as 12705 /* This is a TTY frame, i.e. character hpos/vpos are used as
12707 pixel x/y. */ 12706 pixel x/y. */
12708 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + (has_menu_bar_p ? 1 : 0), 12707 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
12709 TAB_BAR_FACE_ID); 12708 TAB_BAR_FACE_ID);
12710 it.first_visible_x = 0; 12709 it.first_visible_x = 0;
12711 it.last_visible_x = FRAME_COLS (f); 12710 it.last_visible_x = FRAME_COLS (f);
@@ -12737,10 +12736,9 @@ display_tab_bar (struct window *w)
12737 if (NILP (string)) 12736 if (NILP (string))
12738 break; 12737 break;
12739 12738
12740 /* Display the item, pad with one space. */
12741 if (it.current_x < it.last_visible_x) 12739 if (it.current_x < it.last_visible_x)
12742 display_string (NULL, string, Qnil, 0, 0, &it, 12740 display_string (NULL, string, Qnil, 0, 0, &it,
12743 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string)); 12741 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
12744 } 12742 }
12745 12743
12746 /* Fill out the line with spaces. */ 12744 /* Fill out the line with spaces. */
@@ -13159,7 +13157,7 @@ redisplay_tab_bar (struct frame *f)
13159 GLYPH doesn't display a tab-bar item. */ 13157 GLYPH doesn't display a tab-bar item. */
13160 13158
13161static bool 13159static bool
13162tab_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx) 13160tab_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx, bool *close_p)
13163{ 13161{
13164 Lisp_Object prop; 13162 Lisp_Object prop;
13165 int charpos; 13163 int charpos;
@@ -13178,6 +13176,11 @@ tab_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
13178 if (! FIXNUMP (prop)) 13176 if (! FIXNUMP (prop))
13179 return false; 13177 return false;
13180 *prop_idx = XFIXNUM (prop); 13178 *prop_idx = XFIXNUM (prop);
13179
13180 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
13181 Qclose,
13182 f->current_tab_bar_string));
13183
13181 return true; 13184 return true;
13182} 13185}
13183 13186
@@ -13194,7 +13197,7 @@ tab_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
13194 13197
13195static int 13198static int
13196get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph, 13199get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
13197 int *hpos, int *vpos, int *prop_idx) 13200 int *hpos, int *vpos, int *prop_idx, bool *close_p)
13198{ 13201{
13199 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); 13202 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
13200 struct window *w = XWINDOW (f->tab_bar_window); 13203 struct window *w = XWINDOW (f->tab_bar_window);
@@ -13207,7 +13210,7 @@ get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
13207 13210
13208 /* Get the start of this tab-bar item's properties in 13211 /* Get the start of this tab-bar item's properties in
13209 f->tab_bar_items. */ 13212 f->tab_bar_items. */
13210 if (!tab_bar_item_info (f, *glyph, prop_idx)) 13213 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
13211 return -1; 13214 return -1;
13212 13215
13213 /* Is mouse on the highlighted item? */ 13216 /* Is mouse on the highlighted item? */
@@ -13238,6 +13241,7 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
13238 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); 13241 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
13239 struct window *w = XWINDOW (f->tab_bar_window); 13242 struct window *w = XWINDOW (f->tab_bar_window);
13240 int hpos, vpos, prop_idx; 13243 int hpos, vpos, prop_idx;
13244 bool close_p;
13241 struct glyph *glyph; 13245 struct glyph *glyph;
13242 Lisp_Object enabled_p; 13246 Lisp_Object enabled_p;
13243 int ts; 13247 int ts;
@@ -13250,7 +13254,7 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
13250 highlight, since tab-bar items are not highlighted in that 13254 highlight, since tab-bar items are not highlighted in that
13251 case. */ 13255 case. */
13252 frame_to_window_pixel_xy (w, &x, &y); 13256 frame_to_window_pixel_xy (w, &x, &y);
13253 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx); 13257 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
13254 if (ts == -1 13258 if (ts == -1
13255 || (ts != 0 && !NILP (Vmouse_highlight))) 13259 || (ts != 0 && !NILP (Vmouse_highlight)))
13256 return; 13260 return;
@@ -13294,7 +13298,7 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
13294 event.kind = TAB_BAR_EVENT; 13298 event.kind = TAB_BAR_EVENT;
13295 event.frame_or_window = frame; 13299 event.frame_or_window = frame;
13296 event.arg = key; 13300 event.arg = key;
13297 event.modifiers = modifiers; 13301 event.modifiers = close_p ? ctrl_modifier | modifiers : modifiers;
13298 kbd_buffer_store_event (&event); 13302 kbd_buffer_store_event (&event);
13299 f->last_tab_bar_item = -1; 13303 f->last_tab_bar_item = -1;
13300 } 13304 }
@@ -13318,6 +13322,7 @@ note_tab_bar_highlight (struct frame *f, int x, int y)
13318 int i; 13322 int i;
13319 Lisp_Object enabled_p; 13323 Lisp_Object enabled_p;
13320 int prop_idx; 13324 int prop_idx;
13325 bool close_p;
13321 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED; 13326 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
13322 bool mouse_down_p; 13327 bool mouse_down_p;
13323 int rc; 13328 int rc;
@@ -13330,7 +13335,7 @@ note_tab_bar_highlight (struct frame *f, int x, int y)
13330 return; 13335 return;
13331 } 13336 }
13332 13337
13333 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx); 13338 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
13334 if (rc < 0) 13339 if (rc < 0)
13335 { 13340 {
13336 /* Not on tab-bar item. */ 13341 /* Not on tab-bar item. */
@@ -20803,11 +20808,13 @@ do nothing. */)
20803{ 20808{
20804#if defined (HAVE_WINDOW_SYSTEM) 20809#if defined (HAVE_WINDOW_SYSTEM)
20805 struct frame *sf = SELECTED_FRAME (); 20810 struct frame *sf = SELECTED_FRAME ();
20806 struct glyph_matrix *m = XWINDOW (sf->tab_bar_window)->current_matrix; 20811 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
20812 ? XWINDOW (sf->tab_bar_window)->current_matrix
20813 : sf->current_matrix;
20807 EMACS_INT vpos; 20814 EMACS_INT vpos;
20808 20815
20809 if (NILP (row)) 20816 if (NILP (row))
20810 vpos = 0; 20817 vpos = WINDOWP (sf->tab_bar_window) ? 0 : FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
20811 else 20818 else
20812 { 20819 {
20813 CHECK_FIXNUM (row); 20820 CHECK_FIXNUM (row);