[Top][All Lists]

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

Re: Context menus and mouse-3

From: Stefan Monnier
Subject: Re: Context menus and mouse-3
Date: Mon, 12 Jul 2021 18:32:17 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

Juri Linkov [2021-07-12 02:38:19] wrote:
> This is a much needed feature and it would nice to finish it one way or 
> another.
> I tried to use timers, and the result works well in all test cases:
> +    (setq mouse--down-3-timer
> +          (run-with-timer
> +           (/ (abs mouse-3-down-context-menu) 1000.0) nil
> +           (lambda ()
> +             (setq mouse--down-3-timer t)
> +             (unless (eq (posn-window (event-end event)) (selected-window))
> +               (select-window (posn-window (event-end event))))
> +             (mouse-context-menu event))))
> (defun mouse-context-menu (event)
>   "Show a context menu for the current buffer."
>   (interactive "@e")
>   (popup-menu (mouse-context-menu-map) event))

I'm a bit busy with other things these days, but just looking at the
above code, one thing I see as a potential problem with this code is
that the context menu commands won't be run "the normal way": the
undo-boundary won't be applied as usual, post/pre-command-hook won't be
run as usual, etc...

> The global binding of [menu-bar] is defined in menu-bar.el,
> so the same way [context-menu] could be defined globally

Agreed, and I think it would address the above problem.
I.e. do something like

    (defun mouse-context-menu (event)
      (push `(context-menu . ,(cdr event)) unread-command-events))

BTW, the other worry with your code is that if you use an input device
which can fail to pair the down/up mouse-3 events, you might end up
failing to cancel the timer code (that can also happen when the users
set a binding for `drag-mouse-3`, I think), so maybe you should arrange
for the down event to register a `pre-command-hook` that cancels
the timer.

In terms of aesthetics, it would be good to arrange the code such that
`mouse--click-3-maybe-context-menu` doesn't need to duplicate/mimic the
tests performed in `mouse-maybe-context-menu`.  Maybe have
`mouse-maybe-context-menu` set some var telling
`mouse--click-3-maybe-context-menu` when the next `mouse-3` should
be dropped?


PS: FWIW, the "proof of concept" code I have in my local Emacs is:

    (global-set-key [down-mouse-3] #'mouse-maybe-context-menu)
    (defun mouse-maybe-context-menu (event)
      "Bring up a context menu for a long click."
      (interactive "@e")
      (if (let* ((track-mouse t)
                 (time (/ mouse-long-click-time 1000.0))
                 (result (sit-for time)))
            (message "Maybe-context-menu: %S %S" time result)
          (push (cons 'context-menu (cdr event)) unread-command-events)))

I think `sit-for` can be made to work OK, but my proof-of-concept
isn't good enough.  I think the main issue is that it doesn't
swallow the mouse-3 click, but I haven't really looked into it.

reply via email to

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