emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master fd1379a: Support mouse events clicked on the tab bar but outside


From: Juri Linkov
Subject: master fd1379a: Support mouse events clicked on the tab bar but outside of any tab (bug#41343)
Date: Mon, 13 Sep 2021 04:15:45 -0400 (EDT)

branch: master
commit fd1379a85aafa77c119b9b7aa811f669c575bac7
Author: Juri Linkov <juri@linkov.net>
Commit: Juri Linkov <juri@linkov.net>

    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.
---
 lisp/tab-bar.el | 118 ++++++++++++++++++++++++++++++++++----------------------
 src/xdisp.c     |   2 +-
 2 files changed, 73 insertions(+), 47 deletions(-)

diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 2684ff9..e0eb62c 100644
--- a/lisp/tab-bar.el
+++ b/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")))
-
-    (define-key-after menu [close]
-      `(menu-item "Close" (lambda () (interactive)
-                            (tab-bar-close-tab ,tab-number))
-                  :help "Close the tab"))
+         (menu (make-sparse-keymap (propertize "Context Menu" 'hide t))))
+
+    (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)
@@ -352,6 +353,32 @@ 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.
 If t, the default, enable `tab-bar-mode' automatically upon using
@@ -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))
diff --git a/src/xdisp.c b/src/xdisp.c
index 45c7090..d30a685 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -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);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]