GNU bug report logs -
#70086
Mouse clicks in tab-bar don't call commands bound in keymap properties
Previous Next
Reported by: Adam Porter <adam <at> alphapapa.net>
Date: Sat, 30 Mar 2024 02:26:01 UTC
Severity: normal
Fixed in version 30.0.50
Done: Juri Linkov <juri <at> linkov.net>
Bug is archived. No further changes may be made.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 70086 in the body.
You can then email your comments to 70086 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Sat, 30 Mar 2024 02:26:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Adam Porter <adam <at> alphapapa.net>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Sat, 30 Mar 2024 02:26:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
Hi Juri, et al,
In my listen.el package on GNU ELPA, I'm trying to make mouse clicks in
the `global-mode-string' construct work when `mode-line-misc-info' is
shown in the tab-bar by including `tab-bar-format-global' in
`tab-bar-format'. I'm including this construct in the `global-mode-string':
`(listen-mode (:propertize listen-mode-lighter
keymap ,listen-mode-lighter-map))
Using this keymap:
(defvar listen-mode-lighter-map
(let ((map (make-sparse-keymap)))
(define-key map [mode-line mouse-1] #'listen-pause)
(define-key map [tab-bar mouse-1] #'listen-pause)
(define-key map [tab-bar mouse-2] #'listen-pause)
(define-key map [tab-bar mouse-3] #'listen-pause)
(define-key map [tab-bar down-mouse-1] #'listen-pause)
(define-key map [tab-bar down-mouse-2] #'listen-pause)
(define-key map [tab-bar down-mouse-3] #'listen-pause)
map))
When that construct is used in `mode-line-format', it works as expected:
clicking with mouse-1 calls the command `listen-pause'.
But when that same construct is shown in the tab-bar, mouse-1 and
mouse-2 clicks have no effect, and mouse-3 shows the tab-bar context
menu with options for "New tab" and "Reopen closed tab".
Surprisingly, using the sequence "C-h k mouse-1" on the construct in the
tab-bar shows that the binding appears to be read correctly:
There were several key-sequences:
<tab-bar> <down-mouse-1> at that spot runs the command listen-pause
<tab-bar> <mouse-1> at that spot runs the command listen-pause
They're all described below.
<tab-bar> <down-mouse-1> at that spot runs the command listen-pause
(found in listen-mode-lighter-map), which is an interactive
native-compiled Lisp function in ‘listen.el’.
(listen-pause PLAYER)
Pause/unpause PLAYER.
Interactively, uses the default player.
<tab-bar> <mouse-1> at that spot runs the command listen-pause (found
in listen-mode-lighter-map), which is an interactive native-compiled
Lisp function in ‘listen.el’.
(listen-pause PLAYER)
Pause/unpause PLAYER.
Interactively, uses the default player.
But when used without "C-h k", it has no effect.
Looking at tab-bar.el, I see that it does some, I suppose, unusual
things with keymaps and clicks to make them work. However, if this
could be fixed to allow these commands to work properly, it would be
very useful, as the extra space in the tab-bar is a great place to
display extra information without crowding the mode line.
Thanks,
Adam
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Sat, 30 Mar 2024 18:25:03 GMT)
Full text and
rfc822 format available.
Message #8 received at 70086 <at> debbugs.gnu.org (full text, mbox):
> In my listen.el package on GNU ELPA, I'm trying to make mouse clicks in the
> `global-mode-string' construct work when `mode-line-misc-info' is shown in
> the tab-bar by including `tab-bar-format-global' in `tab-bar-format'. I'm
> including this construct in the `global-mode-string':
>
>
> `(listen-mode (:propertize listen-mode-lighter
> keymap ,listen-mode-lighter-map))
Thanks for the request. If possible could you send a minimal test case
to see what exactly do you need.
> When that construct is used in `mode-line-format', it works as expected:
> clicking with mouse-1 calls the command `listen-pause'.
And the same should work on `tab-line-format' as well.
> Looking at tab-bar.el, I see that it does some, I suppose, unusual things
> with keymaps and clicks to make them work. However, if this could be fixed
> to allow these commands to work properly, it would be very useful, as the
> extra space in the tab-bar is a great place to display extra information
> without crowding the mode line.
Indeed, events on the tab-bar have a different design where
`tab-bar--event-to-item' should be used to get a bound command.
You can see an example in `tab-bar-mouse-down-1' that uses
(if (functionp (nth 1 item)) (call-interactively (nth 1 item))
to call an arbitrary command.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Sat, 30 Mar 2024 18:57:02 GMT)
Full text and
rfc822 format available.
Message #11 received at 70086 <at> debbugs.gnu.org (full text, mbox):
> Cc: 70086 <at> debbugs.gnu.org
> From: Juri Linkov <juri <at> linkov.net>
> Date: Sat, 30 Mar 2024 20:16:50 +0200
>
> > Looking at tab-bar.el, I see that it does some, I suppose, unusual things
> > with keymaps and clicks to make them work. However, if this could be fixed
> > to allow these commands to work properly, it would be very useful, as the
> > extra space in the tab-bar is a great place to display extra information
> > without crowding the mode line.
>
> Indeed, events on the tab-bar have a different design where
> `tab-bar--event-to-item' should be used to get a bound command.
> You can see an example in `tab-bar-mouse-down-1' that uses
> (if (functionp (nth 1 item)) (call-interactively (nth 1 item))
> to call an arbitrary command.
The disparity between what "C-h k" says about mouse clicks on the
tab-bar and how to bind commands to such clicks, is IMO a misfeature
that we should fix.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Sun, 31 Mar 2024 16:16:02 GMT)
Full text and
rfc822 format available.
Message #14 received at 70086 <at> debbugs.gnu.org (full text, mbox):
Hi Juri,
On 3/30/24 13:16, Juri Linkov wrote:
>> In my listen.el package on GNU ELPA, I'm trying to make mouse clicks in the
>> `global-mode-string' construct work when `mode-line-misc-info' is shown in
>> the tab-bar by including `tab-bar-format-global' in `tab-bar-format'. I'm
>> including this construct in the `global-mode-string':
>>
>>
>> `(listen-mode (:propertize listen-mode-lighter
>> keymap ,listen-mode-lighter-map))
>
> Thanks for the request. If possible could you send a minimal test case
> to see what exactly do you need.
Sure, the following code in a clean Emacs config seems to demonstrate
the problem:
(require 'cl-lib)
(defvar tab-bar-ecm-keymap
(let ((map (make-sparse-keymap)))
(define-key map [tab-bar mouse-1] (lambda (&rest _)
(interactive)
(message "tab-bar-ecm-lighter
clicked with mouse-1")))
map))
(defvar tab-bar-ecm-lighter "TAB-BAR-ECM-LIGHTER")
(define-minor-mode tab-bar-ecm-mode "DOCSTRING"
:global t
(let ((lighter `(tab-bar-ecm-mode
(:propertize tab-bar-ecm-lighter keymap
,tab-bar-ecm-keymap))))
(if tab-bar-ecm-mode
(progn
(cl-pushnew lighter global-mode-string :test #'equal)
(unless (memq 'tab-bar-format-global tab-bar-format)
(cl-callf append tab-bar-format '(tab-bar-format-global))))
(cl-callf2 remove lighter global-mode-string))))
Evaluate that code and then enable `tab-bar-mode' and
`tab-bar-ecm-mode'. Then you can see that "C-h k" followed by a click
on the "TAB-BAR-ECM-LIGHTER" text in the tab-bar shows that the
anonymous command is bound to that sequence, yet clicking the text
doesn't call it.
> And the same should work on `tab-line-format' as well.
I haven't tried that, but sure, sounds good to me. :)
> Indeed, events on the tab-bar have a different design where
> `tab-bar--event-to-item' should be used to get a bound command.
> You can see an example in `tab-bar-mouse-down-1' that uses
> (if (functionp (nth 1 item)) (call-interactively (nth 1 item))
> to call an arbitrary command.
I see, thanks.
--Adam
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Fri, 05 Apr 2024 16:32:02 GMT)
Full text and
rfc822 format available.
Message #17 received at 70086 <at> debbugs.gnu.org (full text, mbox):
> Sure, the following code in a clean Emacs config seems to demonstrate the
> problem:
Thanks for the test case. And sorry there is no quick fix.
The problem is that the tab-bar uses the architecture completely
different from the mode-line.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Fri, 05 Apr 2024 18:43:01 GMT)
Full text and
rfc822 format available.
Message #20 received at 70086 <at> debbugs.gnu.org (full text, mbox):
Hi Juri,
On 4/5/24 11:29, Juri Linkov wrote:
>> Sure, the following code in a clean Emacs config seems to demonstrate the
>> problem:
>
> Thanks for the test case. And sorry there is no quick fix.
> The problem is that the tab-bar uses the architecture completely
> different from the mode-line.
Understood, that's what I figured. Do you think this could be fixed in
time for Emacs 30?
Thanks,
Adam
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Wed, 10 Apr 2024 06:54:03 GMT)
Full text and
rfc822 format available.
Message #23 received at 70086 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
> Do you think this could be fixed in time for Emacs 30?
Please try out the following patch. At least it works for your test case.
[tab-bar-global.patch (text/x-diff, inline)]
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index cd076664faf..1a80f3d99e7 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -298,9 +298,13 @@ tab-bar--event-to-item
nil otherwise."
(setq tab-bar--dragging-in-progress nil)
(if (posn-window posn)
- (let ((caption (car (posn-string posn))))
- (when caption
- (get-text-property 0 'menu-item caption)))
+ (let* ((caption (car (posn-string posn)))
+ (menu-item (when caption
+ (get-text-property 0 'menu-item caption))))
+ (when (equal menu-item '(global ignore nil))
+ (setf (nth 1 menu-item)
+ (key-binding (vector 'tab-bar last-nonmenu-event) t)))
+ menu-item)
;; Text-mode emulation of switching tabs on the tab bar.
;; This code is used when you click the mouse in the tab bar
;; on a console which has no window system but does have a mouse.
@@ -332,7 +336,7 @@ tab-bar-mouse-down-1
(setq tab-bar--dragging-in-progress t)
;; Don't close the tab when clicked on the close button. Also
;; don't add new tab on down-mouse. Let `tab-bar-mouse-1' do this.
- (unless (or (memq (car item) '(add-tab history-back history-forward))
+ (unless (or (memq (car item) '(add-tab history-back history-forward global))
(nth 2 item))
(if (functionp (nth 1 item))
(call-interactively (nth 1 item))
@@ -347,7 +351,7 @@ tab-bar-mouse-1
(let* ((item (tab-bar--event-to-item (event-start event)))
(tab-number (tab-bar--key-to-number (nth 0 item))))
(cond
- ((and (memq (car item) '(add-tab history-back history-forward))
+ ((and (memq (car item) '(add-tab history-back history-forward global))
(functionp (nth 1 item)))
(call-interactively (nth 1 item)))
((and (nth 2 item) (not (eq tab-number t)))
@@ -468,8 +472,8 @@ tab-bar-touchscreen-begin
(tab-bar-select-tab number))))
;; Cancel the timer.
(cancel-timer timer)))
- ((and (memq (car item) '(add-tab history-back
- history-forward))
+ ((and (memq (car item) '( add-tab history-back
+ history-forward global))
(functionp (cadr item)))
;; This is some kind of button. Wait for the
;; tap to complete and press it.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Thu, 02 May 2024 17:57:02 GMT)
Full text and
rfc822 format available.
Message #26 received at 70086 <at> debbugs.gnu.org (full text, mbox):
close 70086 30.0.50
thanks
>> Do you think this could be fixed in time for Emacs 30?
>
> Please try out the following patch. At least it works for your test case.
I guess this patch did the right thing. So pushed now for Emacs 30.
bug marked as fixed in version 30.0.50, send any further explanations to
70086 <at> debbugs.gnu.org and Adam Porter <adam <at> alphapapa.net>
Request was from
Juri Linkov <juri <at> linkov.net>
to
control <at> debbugs.gnu.org
.
(Thu, 02 May 2024 17:57:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Fri, 03 May 2024 05:46:01 GMT)
Full text and
rfc822 format available.
Message #31 received at 70086 <at> debbugs.gnu.org (full text, mbox):
reopen 70086
thanks
Hi Juri,
On 5/2/24 12:55, Juri Linkov wrote:
> close 70086 30.0.50
> thanks
>
>>> Do you think this could be fixed in time for Emacs 30?
>>
>> Please try out the following patch. At least it works for your test case.
>
> I guess this patch did the right thing. So pushed now for Emacs 30.
Apologies for not replying yet, and thanks for following up. I just
tested your patch, and it almost works perfectly. The problem now is
that if there are multiple such constructs in the tab-bar, each with
their own keymap, it seems that the first one in the global-mode-string
catches the clicks that are made on the second one.
For example, given this value for global-mode-string:
((tab-bar-ecm-mode
(:propertize tab-bar-ecm-lighter keymap
(keymap
(tab-bar keymap
(mouse-1 lambda
(&rest _)
(interactive)
(message "tab-bar-ecm-lighter clicked with mouse-1"))))))
(listen-mode
(:propertize listen-mode-lighter keymap
(keymap
(tab-bar keymap
(down-mouse-3 . listen-pause)
(down-mouse-2 . listen-pause)
(down-mouse-1 . listen-pause)
(mouse-3 . listen-pause)
(mouse-2 . listen-pause)
(mouse-1 . listen-pause))
(mode-line keymap
(mouse-1 . listen-pause))))))
When I click on the text rendered by listen-mode-lighter, the lambda
from the tab-bar-ecm-lighter keymap intercepts the mouse-1 event and
prints the message rather than calling the listen-pause function.
bug No longer marked as fixed in versions 30.0.50 and reopened.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Fri, 03 May 2024 05:46:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Fri, 03 May 2024 06:26:01 GMT)
Full text and
rfc822 format available.
Message #36 received at 70086 <at> debbugs.gnu.org (full text, mbox):
> For example, given this value for global-mode-string:
>
> ((tab-bar-ecm-mode
> (:propertize tab-bar-ecm-lighter keymap
> (keymap
> (tab-bar keymap
> (mouse-1 lambda
> (&rest _)
> (interactive)
> (message "tab-bar-ecm-lighter clicked with mouse-1"))))))
> (listen-mode
> (:propertize listen-mode-lighter keymap
> (keymap
> (tab-bar keymap
> (down-mouse-3 . listen-pause)
> (down-mouse-2 . listen-pause)
> (down-mouse-1 . listen-pause)
> (mouse-3 . listen-pause)
> (mouse-2 . listen-pause)
> (mouse-1 . listen-pause))
> (mode-line keymap
> (mouse-1 . listen-pause))))))
>
> When I click on the text rendered by listen-mode-lighter, the lambda from
> the tab-bar-ecm-lighter keymap intercepts the mouse-1 event and prints the
> message rather than calling the listen-pause function.
Could you please distill this example into a self-contained test case
like you did the previous time, that helped a lot.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Sat, 04 May 2024 04:16:02 GMT)
Full text and
rfc822 format available.
Message #39 received at 70086 <at> debbugs.gnu.org (full text, mbox):
> Could you please distill this example into a self-contained test case
> like you did the previous time, that helped a lot.
Ok, the following code seems to demonstrate the problem, with your patch
applied to tab-bar.el:
(require 'cl-lib)
(defvar tab-bar-ecm-keymap
(let ((map (make-sparse-keymap)))
(define-key map [tab-bar mouse-1] (lambda (&rest _)
(interactive)
(message "tab-bar-ecm-lighter clicked with mouse-1")))
map))
(defvar tab-bar-ecm-lighter "TAB-BAR-ECM-LIGHTER ")
(define-minor-mode tab-bar-ecm-mode "DOCSTRING"
:global t
(let ((lighter `(tab-bar-ecm-mode
(:propertize tab-bar-ecm-lighter keymap ,tab-bar-ecm-keymap))))
(if tab-bar-ecm-mode
(progn
(cl-pushnew lighter global-mode-string :test #'equal)
(unless (memq 'tab-bar-format-global tab-bar-format)
(cl-callf append tab-bar-format '(tab-bar-format-global))))
(cl-callf2 remove lighter global-mode-string))))
(defvar tab-bar-ecm-keymap2
(let ((map (make-sparse-keymap)))
(define-key map [tab-bar mouse-1] (lambda (&rest _)
(interactive)
(message "tab-bar-ecm-lighter2 clicked with mouse-1")))
map))
(defvar tab-bar-ecm-lighter2 "TAB-BAR-ECM-LIGHTER2 ")
(define-minor-mode tab-bar-ecm-mode2 "DOCSTRING"
:global t
(let ((lighter `(tab-bar-ecm-mode2
(:propertize tab-bar-ecm-lighter2 keymap ,tab-bar-ecm-keymap2))))
(if tab-bar-ecm-mode2
(progn
(cl-pushnew lighter global-mode-string :test #'equal)
(unless (memq 'tab-bar-format-global tab-bar-format)
(cl-callf append tab-bar-format '(tab-bar-format-global))))
(cl-callf2 remove lighter global-mode-string))))
Enable both tab-bar-ecm-mode and tab-bar-ecm-mode2. Then you'll see
that, regardless of which lighter is clicked in the tab-bar, the lighter
for the mode that was activated last catches the mouse clicks for both
lighters.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Sun, 05 May 2024 07:02:02 GMT)
Full text and
rfc822 format available.
Message #42 received at 70086 <at> debbugs.gnu.org (full text, mbox):
>> Could you please distill this example into a self-contained test case
>> like you did the previous time, that helped a lot.
>
> Ok, the following code seems to demonstrate the problem, with your patch
> applied to tab-bar.el:
Thanks, now the problem is clear. Your code also demonstrates that
'C-h k mouse-1' shows a wrong binding.
> Enable both tab-bar-ecm-mode and tab-bar-ecm-mode2. Then you'll see that,
> regardless of which lighter is clicked in the tab-bar, the lighter for the
> mode that was activated last catches the mouse clicks for both lighters.
To get a binding at the click location in the string tried to use posn-col-row,
but it returns a wrong coordinate since it doesn't take into account
line-spacing properties.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#70086
; Package
emacs
.
(Mon, 06 May 2024 16:51:02 GMT)
Full text and
rfc822 format available.
Message #45 received at 70086 <at> debbugs.gnu.org (full text, mbox):
close 70086 30.0.50
thanks
>> Could you please distill this example into a self-contained test case
>> like you did the previous time, that helped a lot.
>
> Ok, the following code seems to demonstrate the problem, with your patch
> applied to tab-bar.el:
> [...]
> Enable both tab-bar-ecm-mode and tab-bar-ecm-mode2. Then you'll see that,
> regardless of which lighter is clicked in the tab-bar, the lighter for the
> mode that was activated last catches the mouse clicks for both lighters.
Thanks for the comprehensive test case.
So this feature is now implemented by the following patch and pushed:
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 2e3d9a6b4ac..26023f24389 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -1119,7 +1119,9 @@ tab-bar-format-global
then modes that display information on the mode line
using `global-mode-string' will display the same text
on the tab bar instead."
- `((global menu-item ,(format-mode-line global-mode-string) ignore)))
+ (mapcar (lambda (string)
+ `(global menu-item ,(format-mode-line string) ignore))
+ global-mode-string))
bug marked as fixed in version 30.0.50, send any further explanations to
70086 <at> debbugs.gnu.org and Adam Porter <adam <at> alphapapa.net>
Request was from
Juri Linkov <juri <at> linkov.net>
to
control <at> debbugs.gnu.org
.
(Mon, 06 May 2024 16:51:02 GMT)
Full text and
rfc822 format available.
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Tue, 04 Jun 2024 11:24:14 GMT)
Full text and
rfc822 format available.
This bug report was last modified 1 year and 17 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.