diff options
| author | Juri Linkov | 2019-09-15 23:52:22 +0300 |
|---|---|---|
| committer | Juri Linkov | 2019-09-15 23:52:22 +0300 |
| commit | 6474abc36359a438338e5d6186dbeaf24f200387 (patch) | |
| tree | 1d7a4c74483031759169d66a3b12aa722635240c | |
| parent | 8d30e1bce3c1bddf85272fa31b7d314ed421d29e (diff) | |
| download | emacs-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/README | 8 | ||||
| -rw-r--r-- | etc/images/tabs/close.xpm | 16 | ||||
| -rw-r--r-- | etc/images/tabs/new.xpm | 16 | ||||
| -rw-r--r-- | lisp/tab-bar.el | 157 | ||||
| -rw-r--r-- | lisp/tab-line.el | 129 | ||||
| -rw-r--r-- | src/xdisp.c | 35 |
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 @@ | |||
| 1 | This directory contains icons for the Tabs user interface. | ||
| 2 | |||
| 3 | COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES | ||
| 4 | |||
| 5 | Files: close.xpm new.xpm | ||
| 6 | Author: Juri Linkov <juri@linkov.net> | ||
| 7 | Copyright (C) 2019 Free Software Foundation, Inc. | ||
| 8 | License: 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 */ | ||
| 2 | static 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 */ | ||
| 2 | static 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. |
| 104 | This command is used when you click the mouse in the tab-bar | 112 | This command is used when you click the mouse in the tab-bar |
| 105 | on a console which has no window system but does have a mouse." | 113 | on 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 | ||
| 13161 | static bool | 13159 | static bool |
| 13162 | tab_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx) | 13160 | tab_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 | ||
| 13195 | static int | 13198 | static int |
| 13196 | get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph, | 13199 | get_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); |