Support mouse events clicked on the tab bar but outside of any tab (bug#41343)
* lisp/tab-bar.el (tab-bar--key-to-number): Return non-nil non-numeric t when no tab is used. Return nil for current-tab. (tab-bar-mouse-select-tab, tab-bar-mouse-close-tab): Do nothing when tab-bar--key-to-number returns non-nil non-numeric t for click events outside of any tab. (tab-bar-mouse-context-menu): Add context menu when mouse is clicked outside of tabs. Add "Duplicate" alongside with "Close" to the menu used when mouse is clicked on a tab. (toggle-tab-bar-mode-from-frame, toggle-frame-tab-bar): Move code closer to 'tab-bar-show'. * src/xdisp.c (handle_tab_bar_click): Return Qtab_bar with empty list when mouse is clicked on the tab bar but outside of any tab.
This commit is contained in:
parent
4ee8b4d225
commit
fd1379a85a
2 changed files with 72 additions and 46 deletions
116
lisp/tab-bar.el
116
lisp/tab-bar.el
|
@ -113,7 +113,6 @@ For easier selection of tabs by their numbers, consider customizing
|
|||
:group 'tab-bar
|
||||
:version "27.1")
|
||||
|
||||
|
||||
(defun tab-bar--define-keys ()
|
||||
"Install key bindings for switching between tabs if the user has configured them."
|
||||
(when tab-bar-select-tab-modifiers
|
||||
|
@ -224,10 +223,15 @@ a list of frames to update."
|
|||
(tab-bar--define-keys)
|
||||
(tab-bar--undefine-keys)))
|
||||
|
||||
|
||||
;;; Key bindings
|
||||
|
||||
(defun tab-bar--key-to-number (key)
|
||||
(let ((key-name (format "%S" key)))
|
||||
(when (string-prefix-p "tab-" key-name)
|
||||
(string-to-number (string-replace "tab-" "" key-name)))))
|
||||
(unless (eq key 'current-tab)
|
||||
(let ((key-name (format "%S" key)))
|
||||
(if (string-prefix-p "tab-" key-name)
|
||||
(string-to-number (string-replace "tab-" "" key-name))
|
||||
t))))
|
||||
|
||||
(defun tab-bar--event-to-item (posn)
|
||||
(if (posn-window posn)
|
||||
|
@ -246,37 +250,59 @@ a list of frames to update."
|
|||
(lambda (key binding)
|
||||
(when (eq (car-safe binding) 'menu-item)
|
||||
(when (> (+ column (length (nth 1 binding))) x-position)
|
||||
(throw 'done (list
|
||||
key (nth 2 binding)
|
||||
(get-text-property
|
||||
(- x-position column) 'close-tab (nth 1 binding)))))
|
||||
(throw 'done (list key (nth 2 binding)
|
||||
(get-text-property
|
||||
(- x-position column)
|
||||
'close-tab (nth 1 binding)))))
|
||||
(setq column (+ column (length (nth 1 binding))))))
|
||||
keymap))))))
|
||||
|
||||
(defun tab-bar-mouse-select-tab (event)
|
||||
(interactive "e")
|
||||
(let ((item (tab-bar--event-to-item (event-start event))))
|
||||
(let* ((item (tab-bar--event-to-item (event-start event)))
|
||||
(tab-number (tab-bar--key-to-number (nth 0 item))))
|
||||
(if (nth 2 item)
|
||||
(tab-bar-close-tab (tab-bar--key-to-number (nth 0 item)))
|
||||
(unless (eq tab-number t)
|
||||
(tab-bar-close-tab tab-number))
|
||||
(if (functionp (nth 1 item))
|
||||
(call-interactively (nth 1 item))
|
||||
(tab-bar-select-tab (tab-bar--key-to-number (nth 0 item)))))))
|
||||
(unless (eq tab-number t)
|
||||
(tab-bar-select-tab tab-number))))))
|
||||
|
||||
(defun tab-bar-mouse-close-tab (event)
|
||||
(interactive "e")
|
||||
(let ((item (tab-bar--event-to-item (event-start event))))
|
||||
(tab-bar-close-tab (tab-bar--key-to-number (nth 0 item)))))
|
||||
(let* ((item (tab-bar--event-to-item (event-start event)))
|
||||
(tab-number (tab-bar--key-to-number (nth 0 item))))
|
||||
(unless (eq tab-number t)
|
||||
(tab-bar-close-tab tab-number))))
|
||||
|
||||
(defun tab-bar-mouse-context-menu (event)
|
||||
(interactive "e")
|
||||
(let* ((item (tab-bar--event-to-item (event-start event)))
|
||||
(tab-number (tab-bar--key-to-number (nth 0 item)))
|
||||
(menu (make-sparse-keymap "Context Menu")))
|
||||
(menu (make-sparse-keymap (propertize "Context Menu" 'hide t))))
|
||||
|
||||
(define-key-after menu [close]
|
||||
`(menu-item "Close" (lambda () (interactive)
|
||||
(tab-bar-close-tab ,tab-number))
|
||||
:help "Close the tab"))
|
||||
(cond
|
||||
((eq tab-number t)
|
||||
(define-key-after menu [new-tab]
|
||||
'(menu-item "New tab" tab-bar-new-tab
|
||||
:help "Create a new tab"))
|
||||
(when tab-bar-closed-tabs
|
||||
(define-key-after menu [undo-close]
|
||||
'(menu-item "Reopen closed tab" tab-bar-undo-close-tab
|
||||
:help "Undo closing the tab"))))
|
||||
|
||||
(t
|
||||
(define-key-after menu [duplicate-tab]
|
||||
`(menu-item "Duplicate" (lambda () (interactive)
|
||||
(tab-bar-duplicate-tab
|
||||
nil ;; TODO: add ,tab-number
|
||||
))
|
||||
:help "Duplicate the tab"))
|
||||
(define-key-after menu [close]
|
||||
`(menu-item "Close" (lambda () (interactive)
|
||||
(tab-bar-close-tab ,tab-number))
|
||||
:help "Close the tab"))))
|
||||
|
||||
(popup-menu menu event)))
|
||||
|
||||
|
@ -290,31 +316,6 @@ a list of frames to update."
|
|||
(event-end event))))))
|
||||
(tab-bar-move-tab-to to from)))
|
||||
|
||||
(defun toggle-tab-bar-mode-from-frame (&optional arg)
|
||||
"Toggle tab bar on or off, based on the status of the current frame.
|
||||
Used in the Show/Hide menu, to have the toggle reflect the current frame.
|
||||
See `tab-bar-mode' for more information."
|
||||
(interactive (list (or current-prefix-arg 'toggle)))
|
||||
(if (eq arg 'toggle)
|
||||
(tab-bar-mode (if (> (frame-parameter nil 'tab-bar-lines) 0) 0 1))
|
||||
(tab-bar-mode arg)))
|
||||
|
||||
(defun toggle-frame-tab-bar (&optional frame)
|
||||
"Toggle tab bar of the selected frame.
|
||||
When calling from Lisp, use the optional argument FRAME to toggle
|
||||
the tab bar on that frame.
|
||||
This is useful if you want to enable the tab bar individually
|
||||
on each new frame when the global `tab-bar-mode' is disabled,
|
||||
or if you want to disable the tab bar individually on each
|
||||
new frame when the global `tab-bar-mode' is enabled, by using
|
||||
|
||||
(add-hook 'after-make-frame-functions 'toggle-frame-tab-bar)"
|
||||
(interactive)
|
||||
(set-frame-parameter frame 'tab-bar-lines
|
||||
(if (> (frame-parameter frame 'tab-bar-lines) 0) 0 1))
|
||||
(set-frame-parameter frame 'tab-bar-lines-keep-state
|
||||
(not (frame-parameter frame 'tab-bar-lines-keep-state))))
|
||||
|
||||
(defvar tab-bar-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map [down-mouse-1] 'tab-bar-mouse-select-tab)
|
||||
|
@ -351,6 +352,32 @@ Its main job is to show tabs in the tab bar
|
|||
and to bind mouse events to the commands."
|
||||
(tab-bar-make-keymap-1))
|
||||
|
||||
|
||||
(defun toggle-tab-bar-mode-from-frame (&optional arg)
|
||||
"Toggle tab bar on or off, based on the status of the current frame.
|
||||
Used in the Show/Hide menu, to have the toggle reflect the current frame.
|
||||
See `tab-bar-mode' for more information."
|
||||
(interactive (list (or current-prefix-arg 'toggle)))
|
||||
(if (eq arg 'toggle)
|
||||
(tab-bar-mode (if (> (frame-parameter nil 'tab-bar-lines) 0) 0 1))
|
||||
(tab-bar-mode arg)))
|
||||
|
||||
(defun toggle-frame-tab-bar (&optional frame)
|
||||
"Toggle tab bar of the selected frame.
|
||||
When calling from Lisp, use the optional argument FRAME to toggle
|
||||
the tab bar on that frame.
|
||||
This is useful if you want to enable the tab bar individually
|
||||
on each new frame when the global `tab-bar-mode' is disabled,
|
||||
or if you want to disable the tab bar individually on each
|
||||
new frame when the global `tab-bar-mode' is enabled, by using
|
||||
|
||||
(add-hook 'after-make-frame-functions 'toggle-frame-tab-bar)"
|
||||
(interactive)
|
||||
(set-frame-parameter frame 'tab-bar-lines
|
||||
(if (> (frame-parameter frame 'tab-bar-lines) 0) 0 1))
|
||||
(set-frame-parameter frame 'tab-bar-lines-keep-state
|
||||
(not (frame-parameter frame 'tab-bar-lines-keep-state))))
|
||||
|
||||
|
||||
(defcustom tab-bar-show t
|
||||
"Defines when to show the tab bar.
|
||||
|
@ -1224,8 +1251,7 @@ where argument addressing is absolute."
|
|||
|
||||
(defun tab-bar-duplicate-tab (&optional arg)
|
||||
"Duplicate the current tab to ARG positions to the right.
|
||||
If a negative ARG, duplicate the tab to ARG positions to the left.
|
||||
If ARG is zero, duplicate the tab in place of the current tab."
|
||||
ARG has the same meaning as in `tab-bar-new-tab'."
|
||||
(interactive "P")
|
||||
(let ((tab-bar-new-tab-choice nil)
|
||||
(tab-bar-new-tab-group t))
|
||||
|
|
|
@ -13774,7 +13774,7 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
|
|||
frame_to_window_pixel_xy (w, &x, &y);
|
||||
ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
|
||||
if (ts == -1)
|
||||
return Qnil;
|
||||
return Fcons (Qtab_bar, Qnil);
|
||||
|
||||
/* If item is disabled, do nothing. */
|
||||
enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
|
||||
|
|
Loading…
Add table
Reference in a new issue