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 /lisp | |
| 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.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/tab-bar.el | 157 | ||||
| -rw-r--r-- | lisp/tab-line.el | 129 |
2 files changed, 159 insertions, 127 deletions
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)))) |