aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuri Linkov2021-09-05 20:16:33 +0300
committerJuri Linkov2021-09-05 20:16:33 +0300
commit794fdce55d097f2b58ce37818edffb2deef7b9de (patch)
tree42c14ae6326ae151f3e943d264074a2671ccda98
parentad9c57f54ae3eea9e5b2fe9264e9edb8b2ed1857 (diff)
downloademacs-794fdce55d097f2b58ce37818edffb2deef7b9de.tar.gz
emacs-794fdce55d097f2b58ce37818edffb2deef7b9de.zip
Improve tab-bar event handling (bug#41343)
* lisp/tab-bar.el (tab-bar--key-to-number): Rename from tab--key-to-number. (tab-bar--event-to-item): New function from tab-bar-handle-mouse. (tab-bar-mouse-select-tab, tab-bar-mouse-close-tab) (tab-bar-mouse-context-menu, tab-bar-mouse-move-tab): Use tab-bar--event-to-item. * src/menu.c (x_popup_menu_1): Handle Qtab_bar in the second list element. * src/xdisp.c (tty_get_tab_bar_item): Change arg 'end' to bool 'close_p'. (tty_get_tab_bar_item): Detect if the close button was clicked. (tty_handle_tab_bar_click): Return a list with caption that has text properties.
-rw-r--r--lisp/tab-bar.el96
-rw-r--r--src/menu.c9
-rw-r--r--src/w32term.c10
-rw-r--r--src/xdisp.c44
-rw-r--r--src/xterm.c10
5 files changed, 82 insertions, 87 deletions
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index ef7babb87b1..aac7bb5d106 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -221,61 +221,53 @@ a list of frames to update."
221 (tab-bar--define-keys) 221 (tab-bar--define-keys)
222 (tab-bar--undefine-keys))) 222 (tab-bar--undefine-keys)))
223 223
224(defun tab--key-to-number (key) 224(defun tab-bar--key-to-number (key)
225 (unless (or (null key) (eq key 'current-tab)) 225 (let ((key-name (format "%S" key)))
226 (string-to-number 226 (when (string-prefix-p "tab-" key-name)
227 (string-replace "tab-" "" (format "%S" key))))) 227 (string-to-number (string-replace "tab-" "" key-name)))))
228 228
229(defun tab-bar-handle-mouse (event) 229(defun tab-bar--event-to-item (posn)
230 "Text-mode emulation of switching tabs on the tab bar. 230 (if (posn-window posn)
231This command is used when you click the mouse in the tab bar 231 (let ((caption (car (posn-string posn))))
232on a console which has no window system but does have a mouse." 232 (when caption
233 (interactive "e") 233 (get-text-property 0 'menu-item caption)))
234 (let* ((x-position (car (posn-x-y (event-start event)))) 234 ;; Text-mode emulation of switching tabs on the tab bar.
235 (keymap (lookup-key (cons 'keymap (nreverse (current-active-maps))) [tab-bar])) 235 ;; This code is used when you click the mouse in the tab bar
236 (column 0)) 236 ;; on a console which has no window system but does have a mouse.
237 (when x-position 237 (let* ((x-position (car (posn-x-y posn)))
238 (unless (catch 'done 238 (keymap (lookup-key (cons 'keymap (nreverse (current-active-maps))) [tab-bar]))
239 (map-keymap 239 (column 0))
240 (lambda (key binding) 240 (when x-position
241 (when (eq (car-safe binding) 'menu-item) 241 (catch 'done
242 (when (> (+ column (length (nth 1 binding))) x-position) 242 (map-keymap
243 (if (get-text-property 243 (lambda (key binding)
244 (- x-position column) 'close-tab (nth 1 binding)) 244 (when (eq (car-safe binding) 'menu-item)
245 (tab-bar-close-tab (tab--key-to-number key)) 245 (when (> (+ column (length (nth 1 binding))) x-position)
246 (if (nth 2 binding) 246 (throw 'done (list
247 (call-interactively (nth 2 binding)) 247 key (nth 2 binding)
248 (tab-bar-select-tab (tab--key-to-number key)))) 248 (get-text-property
249 (throw 'done t)) 249 (- x-position column) 'close-tab (nth 1 binding)))))
250 (setq column (+ column (length (nth 1 binding)))))) 250 (setq column (+ column (length (nth 1 binding))))))
251 keymap)) 251 keymap))))))
252 ;; Clicking anywhere outside existing tabs will add a new tab
253 (tab-bar-new-tab)))))
254 252
255(defun tab-bar-mouse-select-tab (event) 253(defun tab-bar-mouse-select-tab (event)
256 (interactive "e") 254 (interactive "e")
257 (if (posn-window (event-start event)) 255 (let ((item (tab-bar--event-to-item (event-start event))))
258 (let* ((caption (car (posn-string (event-start event)))) 256 (if (nth 2 item)
259 (item (and caption (get-text-property 0 'menu-item caption)))) 257 (tab-bar-close-tab (tab-bar--key-to-number (nth 0 item)))
260 (if (nth 2 item) 258 (if (functionp (nth 1 item))
261 (tab-bar-close-tab (tab--key-to-number (nth 0 item))) 259 (call-interactively (nth 1 item))
262 (if (functionp (nth 1 item)) 260 (tab-bar-select-tab (tab-bar--key-to-number (nth 0 item)))))))
263 (call-interactively (nth 1 item))
264 (tab-bar-select-tab (tab--key-to-number (nth 0 item))))))
265 ;; TTY
266 (tab-bar-handle-mouse event)))
267 261
268(defun tab-bar-mouse-close-tab (event) 262(defun tab-bar-mouse-close-tab (event)
269 (interactive "e") 263 (interactive "e")
270 (let* ((caption (car (posn-string (event-start event)))) 264 (let ((item (tab-bar--event-to-item (event-start event))))
271 (item (and caption (get-text-property 0 'menu-item caption)))) 265 (tab-bar-close-tab (tab-bar--key-to-number (nth 0 item)))))
272 (tab-bar-close-tab (tab--key-to-number (nth 0 item)))))
273 266
274(defun tab-bar-mouse-context-menu (event) 267(defun tab-bar-mouse-context-menu (event)
275 (interactive "e") 268 (interactive "e")
276 (let* ((caption (car (posn-string (event-start event)))) 269 (let* ((item (tab-bar--event-to-item (event-start event)))
277 (item (and caption (get-text-property 0 'menu-item caption))) 270 (tab-number (tab-bar--key-to-number (nth 0 item)))
278 (tab-number (tab--key-to-number (nth 0 item)))
279 (menu (make-sparse-keymap "Context Menu"))) 271 (menu (make-sparse-keymap "Context Menu")))
280 272
281 (define-key-after menu [close] 273 (define-key-after menu [close]
@@ -287,12 +279,12 @@ on a console which has no window system but does have a mouse."
287 279
288(defun tab-bar-mouse-move-tab (event) 280(defun tab-bar-mouse-move-tab (event)
289 (interactive "e") 281 (interactive "e")
290 (let* ((caption (car (posn-string (event-start event)))) 282 (let ((from (tab-bar--key-to-number
291 (item (and caption (get-text-property 0 'menu-item caption))) 283 (nth 0 (tab-bar--event-to-item
292 (from (tab--key-to-number (nth 0 item))) 284 (event-start event)))))
293 (caption (car (posn-string (event-end event)))) 285 (to (tab-bar--key-to-number
294 (item (and caption (get-text-property 0 'menu-item caption))) 286 (nth 0 (tab-bar--event-to-item
295 (to (tab--key-to-number (nth 0 item)))) 287 (event-end event))))))
296 (tab-bar-move-tab-to to from))) 288 (tab-bar-move-tab-to to from)))
297 289
298(defun toggle-tab-bar-mode-from-frame (&optional arg) 290(defun toggle-tab-bar-mode-from-frame (&optional arg)
diff --git a/src/menu.c b/src/menu.c
index 3b1d7402571..990a74b92e3 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -1127,9 +1127,12 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu)
1127 1127
1128 /* Decode the first argument: find the window and the coordinates. */ 1128 /* Decode the first argument: find the window and the coordinates. */
1129 if (EQ (position, Qt) 1129 if (EQ (position, Qt)
1130 || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) 1130 || (CONSP (position)
1131 || EQ (XCAR (position), Qtab_bar) 1131 && (EQ (XCAR (position), Qmenu_bar)
1132 || EQ (XCAR (position), Qtool_bar)))) 1132 || EQ (XCAR (position), Qtab_bar)
1133 || (CONSP (XCDR (position))
1134 && EQ (XCAR (XCDR (position)), Qtab_bar))
1135 || EQ (XCAR (position), Qtool_bar))))
1133 { 1136 {
1134 get_current_pos_p = 1; 1137 get_current_pos_p = 1;
1135 } 1138 }
diff --git a/src/w32term.c b/src/w32term.c
index c9570b0c670..aca4739a2e3 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -5186,7 +5186,7 @@ w32_read_socket (struct terminal *terminal,
5186 { 5186 {
5187 /* If we decide we want to generate an event to be seen 5187 /* If we decide we want to generate an event to be seen
5188 by the rest of Emacs, we put it here. */ 5188 by the rest of Emacs, we put it here. */
5189 Lisp_Object tab_bar_key = Qnil; 5189 Lisp_Object tab_bar_arg = Qnil;
5190 bool tab_bar_p = 0; 5190 bool tab_bar_p = 0;
5191 bool tool_bar_p = 0; 5191 bool tool_bar_p = 0;
5192 int button = 0; 5192 int button = 0;
@@ -5209,12 +5209,12 @@ w32_read_socket (struct terminal *terminal,
5209 5209
5210 if (EQ (window, f->tab_bar_window)) 5210 if (EQ (window, f->tab_bar_window))
5211 { 5211 {
5212 tab_bar_key = w32_handle_tab_bar_click (f, &inev); 5212 tab_bar_arg = w32_handle_tab_bar_click (f, &inev);
5213 tab_bar_p = 1; 5213 tab_bar_p = 1;
5214 } 5214 }
5215 } 5215 }
5216 5216
5217 if ((tab_bar_p && NILP (tab_bar_key)) 5217 if ((tab_bar_p && NILP (tab_bar_arg))
5218 || (dpyinfo->w32_focus_frame 5218 || (dpyinfo->w32_focus_frame
5219 && f != dpyinfo->w32_focus_frame 5219 && f != dpyinfo->w32_focus_frame
5220 /* This does not help when the click happens in 5220 /* This does not help when the click happens in
@@ -5222,8 +5222,8 @@ w32_read_socket (struct terminal *terminal,
5222 && !frame_ancestor_p (f, dpyinfo->w32_focus_frame))) 5222 && !frame_ancestor_p (f, dpyinfo->w32_focus_frame)))
5223 inev.kind = NO_EVENT; 5223 inev.kind = NO_EVENT;
5224 5224
5225 if (!NILP (tab_bar_key)) 5225 if (!NILP (tab_bar_arg))
5226 inev.arg = tab_bar_key; 5226 inev.arg = tab_bar_arg;
5227 5227
5228 /* Is this in the tool-bar? */ 5228 /* Is this in the tool-bar? */
5229 if (WINDOWP (f->tool_bar_window) 5229 if (WINDOWP (f->tool_bar_window)
diff --git a/src/xdisp.c b/src/xdisp.c
index 4a5ab172cc1..91f9bb98e6f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -13891,7 +13891,7 @@ note_tab_bar_highlight (struct frame *f, int x, int y)
13891 13891
13892/* Find the tab-bar item at X coordinate and return its information. */ 13892/* Find the tab-bar item at X coordinate and return its information. */
13893static Lisp_Object 13893static Lisp_Object
13894tty_get_tab_bar_item (struct frame *f, int x, int *idx, ptrdiff_t *end) 13894tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
13895{ 13895{
13896 ptrdiff_t clen = 0; 13896 ptrdiff_t clen = 0;
13897 13897
@@ -13904,8 +13904,11 @@ tty_get_tab_bar_item (struct frame *f, int x, int *idx, ptrdiff_t *end)
13904 clen += SCHARS (caption); 13904 clen += SCHARS (caption);
13905 if (x < clen) 13905 if (x < clen)
13906 { 13906 {
13907 *idx = i; 13907 *prop_idx = i;
13908 *end = clen; 13908 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
13909 - (clen - x)),
13910 Qclose_tab,
13911 caption));
13909 return caption; 13912 return caption;
13910 } 13913 }
13911 } 13914 }
@@ -13928,8 +13931,8 @@ tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
13928 13931
13929 /* Find the tab-bar item where the X,Y coordinates belong. */ 13932 /* Find the tab-bar item where the X,Y coordinates belong. */
13930 int prop_idx; 13933 int prop_idx;
13931 ptrdiff_t clen; 13934 bool close_p;
13932 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &clen); 13935 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
13933 13936
13934 if (NILP (caption)) 13937 if (NILP (caption))
13935 return Qnil; 13938 return Qnil;
@@ -13941,24 +13944,21 @@ tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
13941 if (down_p) 13944 if (down_p)
13942 f->last_tab_bar_item = prop_idx; 13945 f->last_tab_bar_item = prop_idx;
13943 else 13946 else
13944 { 13947 f->last_tab_bar_item = -1;
13945 f->last_tab_bar_item = -1;
13946 }
13947 13948
13948 /* Generate a TAB_BAR_EVENT event. */ 13949 caption = Fcopy_sequence (caption);
13949 Lisp_Object key = AREF (f->tab_bar_items,
13950 prop_idx * TAB_BAR_ITEM_NSLOTS
13951 + TAB_BAR_ITEM_KEY);
13952 /* Kludge alert: we assume the last two characters of a tab
13953 label are " x", and treat clicks on those 2 characters as a
13954 Close Tab command. */
13955 eassert (STRINGP (caption));
13956 int lastc = SSDATA (caption)[SCHARS (caption) - 1];
13957 bool close_p = false;
13958 if ((x == clen - 1 || (clen > 1 && x == clen - 2)) && lastc == 'x')
13959 close_p = true;
13960 13950
13961 return list3 (Qtab_bar, key, close_p ? Qt : Qnil); 13951 AUTO_LIST2 (props, Qmenu_item,
13952 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
13953 + TAB_BAR_ITEM_KEY),
13954 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
13955 + TAB_BAR_ITEM_BINDING),
13956 close_p ? Qt : Qnil));
13957
13958 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
13959 props, caption);
13960
13961 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
13962} 13962}
13963 13963
13964 13964
@@ -33524,7 +33524,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
33524 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))) 33524 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
33525 { 33525 {
33526 int prop_idx; 33526 int prop_idx;
33527 ptrdiff_t ignore; 33527 bool ignore;
33528 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore); 33528 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
33529 33529
33530 if (!NILP (caption)) 33530 if (!NILP (caption))
diff --git a/src/xterm.c b/src/xterm.c
index 57229d3d616..846b67b069f 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -9166,7 +9166,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
9166 { 9166 {
9167 /* If we decide we want to generate an event to be seen 9167 /* If we decide we want to generate an event to be seen
9168 by the rest of Emacs, we put it here. */ 9168 by the rest of Emacs, we put it here. */
9169 Lisp_Object tab_bar_key = Qnil; 9169 Lisp_Object tab_bar_arg = Qnil;
9170 bool tab_bar_p = false; 9170 bool tab_bar_p = false;
9171 bool tool_bar_p = false; 9171 bool tool_bar_p = false;
9172 9172
@@ -9216,7 +9216,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
9216 tab_bar_p = EQ (window, f->tab_bar_window); 9216 tab_bar_p = EQ (window, f->tab_bar_window);
9217 9217
9218 if (tab_bar_p) 9218 if (tab_bar_p)
9219 tab_bar_key = handle_tab_bar_click 9219 tab_bar_arg = handle_tab_bar_click
9220 (f, x, y, event->xbutton.type == ButtonPress, 9220 (f, x, y, event->xbutton.type == ButtonPress,
9221 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state)); 9221 x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
9222 } 9222 }
@@ -9240,7 +9240,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
9240 } 9240 }
9241#endif /* !USE_GTK */ 9241#endif /* !USE_GTK */
9242 9242
9243 if (!(tab_bar_p && NILP (tab_bar_key)) && !tool_bar_p) 9243 if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
9244#if defined (USE_X_TOOLKIT) || defined (USE_GTK) 9244#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
9245 if (! popup_activated ()) 9245 if (! popup_activated ())
9246#endif 9246#endif
@@ -9259,8 +9259,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
9259 else 9259 else
9260 x_construct_mouse_click (&inev.ie, &event->xbutton, f); 9260 x_construct_mouse_click (&inev.ie, &event->xbutton, f);
9261 9261
9262 if (!NILP (tab_bar_key)) 9262 if (!NILP (tab_bar_arg))
9263 inev.ie.arg = tab_bar_key; 9263 inev.ie.arg = tab_bar_arg;
9264 } 9264 }
9265 if (FRAME_X_EMBEDDED_P (f)) 9265 if (FRAME_X_EMBEDDED_P (f))
9266 xembed_send_message (f, event->xbutton.time, 9266 xembed_send_message (f, event->xbutton.time,