* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
@ 2024-03-30 2:25 Adam Porter
2024-03-30 18:16 ` Juri Linkov
0 siblings, 1 reply; 13+ messages in thread
From: Adam Porter @ 2024-03-30 2:25 UTC (permalink / raw)
To: 70086; +Cc: Juri Linkov
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
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-03-30 2:25 bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties Adam Porter
@ 2024-03-30 18:16 ` Juri Linkov
2024-03-30 18:56 ` Eli Zaretskii
2024-03-31 16:15 ` Adam Porter
0 siblings, 2 replies; 13+ messages in thread
From: Juri Linkov @ 2024-03-30 18:16 UTC (permalink / raw)
To: Adam Porter; +Cc: 70086
> 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.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-03-30 18:16 ` Juri Linkov
@ 2024-03-30 18:56 ` Eli Zaretskii
2024-03-31 16:15 ` Adam Porter
1 sibling, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2024-03-30 18:56 UTC (permalink / raw)
To: Juri Linkov; +Cc: adam, 70086
> Cc: 70086@debbugs.gnu.org
> From: Juri Linkov <juri@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.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-03-30 18:16 ` Juri Linkov
2024-03-30 18:56 ` Eli Zaretskii
@ 2024-03-31 16:15 ` Adam Porter
2024-04-05 16:29 ` Juri Linkov
1 sibling, 1 reply; 13+ messages in thread
From: Adam Porter @ 2024-03-31 16:15 UTC (permalink / raw)
To: Juri Linkov; +Cc: 70086
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
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-03-31 16:15 ` Adam Porter
@ 2024-04-05 16:29 ` Juri Linkov
2024-04-05 18:41 ` Adam Porter
0 siblings, 1 reply; 13+ messages in thread
From: Juri Linkov @ 2024-04-05 16:29 UTC (permalink / raw)
To: Adam Porter; +Cc: 70086
> 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.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-04-05 16:29 ` Juri Linkov
@ 2024-04-05 18:41 ` Adam Porter
2024-04-10 6:42 ` Juri Linkov
0 siblings, 1 reply; 13+ messages in thread
From: Adam Porter @ 2024-04-05 18:41 UTC (permalink / raw)
To: Juri Linkov; +Cc: 70086
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
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-04-05 18:41 ` Adam Porter
@ 2024-04-10 6:42 ` Juri Linkov
2024-05-02 17:55 ` Juri Linkov
0 siblings, 1 reply; 13+ messages in thread
From: Juri Linkov @ 2024-04-10 6:42 UTC (permalink / raw)
To: Adam Porter; +Cc: 70086
[-- Attachment #1: Type: text/plain, Size: 134 bytes --]
> 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.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: tab-bar-global.patch --]
[-- Type: text/x-diff, Size: 2546 bytes --]
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.
^ permalink raw reply related [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-04-10 6:42 ` Juri Linkov
@ 2024-05-02 17:55 ` Juri Linkov
2024-05-03 5:45 ` Adam Porter
0 siblings, 1 reply; 13+ messages in thread
From: Juri Linkov @ 2024-05-02 17:55 UTC (permalink / raw)
To: Adam Porter; +Cc: 70086
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.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-05-02 17:55 ` Juri Linkov
@ 2024-05-03 5:45 ` Adam Porter
2024-05-03 6:18 ` Juri Linkov
0 siblings, 1 reply; 13+ messages in thread
From: Adam Porter @ 2024-05-03 5:45 UTC (permalink / raw)
To: Juri Linkov; +Cc: control, 70086
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.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-05-03 5:45 ` Adam Porter
@ 2024-05-03 6:18 ` Juri Linkov
2024-05-04 4:15 ` Adam Porter
0 siblings, 1 reply; 13+ messages in thread
From: Juri Linkov @ 2024-05-03 6:18 UTC (permalink / raw)
To: Adam Porter; +Cc: control, 70086
> 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.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-05-03 6:18 ` Juri Linkov
@ 2024-05-04 4:15 ` Adam Porter
2024-05-05 6:49 ` Juri Linkov
2024-05-06 16:46 ` Juri Linkov
0 siblings, 2 replies; 13+ messages in thread
From: Adam Porter @ 2024-05-04 4:15 UTC (permalink / raw)
To: Juri Linkov; +Cc: control, 70086
> 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.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-05-04 4:15 ` Adam Porter
@ 2024-05-05 6:49 ` Juri Linkov
2024-05-06 16:46 ` Juri Linkov
1 sibling, 0 replies; 13+ messages in thread
From: Juri Linkov @ 2024-05-05 6:49 UTC (permalink / raw)
To: Adam Porter; +Cc: 70086
>> 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.
^ permalink raw reply [flat|nested] 13+ messages in thread
* bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties
2024-05-04 4:15 ` Adam Porter
2024-05-05 6:49 ` Juri Linkov
@ 2024-05-06 16:46 ` Juri Linkov
1 sibling, 0 replies; 13+ messages in thread
From: Juri Linkov @ 2024-05-06 16:46 UTC (permalink / raw)
To: Adam Porter; +Cc: 70086
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))
^ permalink raw reply related [flat|nested] 13+ messages in thread
end of thread, other threads:[~2024-05-06 16:46 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-30 2:25 bug#70086: Mouse clicks in tab-bar don't call commands bound in keymap properties Adam Porter
2024-03-30 18:16 ` Juri Linkov
2024-03-30 18:56 ` Eli Zaretskii
2024-03-31 16:15 ` Adam Porter
2024-04-05 16:29 ` Juri Linkov
2024-04-05 18:41 ` Adam Porter
2024-04-10 6:42 ` Juri Linkov
2024-05-02 17:55 ` Juri Linkov
2024-05-03 5:45 ` Adam Porter
2024-05-03 6:18 ` Juri Linkov
2024-05-04 4:15 ` Adam Porter
2024-05-05 6:49 ` Juri Linkov
2024-05-06 16:46 ` Juri Linkov
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).