[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Context menus and mouse-3
From: |
Juri Linkov |
Subject: |
Re: Context menus and mouse-3 |
Date: |
Mon, 12 Jul 2021 02:38:19 +0300 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (x86_64-pc-linux-gnu) |
>> > We don't need to choose, since we can get a context menu on
>> > `down-mouse-3` and 'mouse-save-then-kill' on `mouse-3`.
>
> (defun mouse-maybe-context-menu (event)
> "Bring up a context menu for a long click.
> See `mouse-long-click-time' and `mouse-context-menu-function'."
> (interactive "@e")
> (if (let ((track-mouse t)) (sit-for (/ mouse-long-click-time 1000.0)))
> (push (cons 'context-menu (cdr event)) unread-command-events)))
>
> It's not good enough for `master` (IIRC the sit-for tends to return nil
> immediately in some circumstances), but I didn't pursue this any further
> given the lack of interest at the time. I can't think of any reason why
> it should be hard to fix.
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:
1. Modes that already bind down-mouse-3 continue working without problems,
so e.g. smerge-popup-context-menu works fine. BTW, while testing it
by clicking down-mouse-3 in non-selected windows, I found a problem,
so a fix for this very rare problem is also included in the patch.
For the same reason 'popup-menu' needs to be called explicitly
to be able to select the right window, as the patch does,
for the case when the mouse is dragged and down-mouse-3
is released in another window.
2. flyspell.el doesn't need to be changed. ibuffer.el works too.
3. cua-rect.el helped to fix one problem and now is supported too.
The new user option mouse-3-down-context-menu is based on
mouse-1-click-follows-link.
Currently mouse-context-menu-map shows just the Edit menu - filling the content
of the context menu with e.g. mouse-context-menu-function is a separate task.
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 89e5d7c48a..febda78212 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -156,6 +156,82 @@ key-translation-map
(define-key key-translation-map [double-mouse-1]
#'mouse--click-1-maybe-follows-link)
+
+(defcustom mouse-3-down-context-menu 450
+ "Non-nil means that holding down Mouse-3 shows context menu.
+
+With the default setting, holding down the Mouse-3 button
+for more than 450 milliseconds performs the same action as S-Down-Mouse-3
+\(which shows the menu), while an ordinary Mouse-3 click performs the
+original Mouse-3 binding (which typically sets the region where you
+click the mouse).
+
+If value is an integer, the time elapsed between pressing and
+releasing the mouse button determines whether to show the menu
+or perform the normal Mouse-3 action (typically set the region).
+The absolute numeric value specifies the maximum duration of a
+\"short click\" in milliseconds. A positive value means that a
+short click shows the menu, and a longer click performs the
+normal action.
+
+Otherwise, a single Mouse-3 click unconditionally shows the menu."
+ :version "28.1"
+ :type '(choice (const :tag "Disabled" nil)
+ (number :tag "Single click time limit" :value 450)
+ (other :tag "Single click" t)))
+
+(defvar mouse--down-3-timer nil)
+
+(defun mouse-maybe-context-menu (event)
+ (interactive "@e")
+ (cond
+ ;; Delay context menu display.
+ ((numberp mouse-3-down-context-menu)
+ (when (timerp mouse--down-3-timer)
+ (cancel-timer mouse--down-3-timer))
+ (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))))
+ nil)
+ ;; Immediately pop up context menu.
+ (mouse-3-down-context-menu
+ (unless (eq (posn-window (event-end event)) (selected-window))
+ (select-window (posn-window (event-end event))))
+ (mouse-context-menu event))))
+
+(defun mouse--click-3-maybe-context-menu (&optional _prompt)
+ (cond
+ ((numberp mouse-3-down-context-menu)
+ (cond
+ ((timerp mouse--down-3-timer)
+ ;; Don't wait for context menu and fall back to mouse-save-then-kill.
+ (cancel-timer mouse--down-3-timer)
+ (setq mouse--down-3-timer nil)
+ nil)
+ (mouse--down-3-timer
+ ;; Context menu was displayed after delay.
+ (setq mouse--down-3-timer nil)
+ [])))
+ ;; Context menu was displayed immediately.
+ (mouse-3-down-context-menu
+ [])))
+
+(define-key key-translation-map [mouse-3]
+ #'mouse--click-3-maybe-context-menu)
+
+(defun mouse-context-menu-map ()
+ (cddr (assq 'edit (lookup-key global-map [menu-bar]))))
+
+(defun mouse-context-menu (event)
+ "Show a context menu for the current buffer."
+ (interactive "@e")
+ (popup-menu (mouse-context-menu-map) event))
+
;; Provide a mode-specific menu on a mouse button.
@@ -1672,7 +1748,7 @@ mouse-save-then-kill
((not (numberp click-pt)) nil)
;; If the user clicked without moving point, kill the region.
;; This also resets `mouse-selection-click-count'.
- ((and (eq last-command 'mouse-save-then-kill)
+ ((and (memq last-command '(mouse-save-then-kill mouse-maybe-context-menu))
(eq click-pt mouse-save-then-kill-posn)
(eq window (selected-window)))
(if mouse-drag-copy-region
@@ -2899,6 +2975,8 @@ function-key-map
;; Allow yanking also when the corresponding cursor is "in the fringe".
(define-key function-key-map [right-fringe mouse-2] 'mouse--strip-first-event)
(define-key function-key-map [left-fringe mouse-2] 'mouse--strip-first-event)
+
+(global-set-key [down-mouse-3] 'mouse-maybe-context-menu)
(global-set-key [mouse-3] 'mouse-save-then-kill)
(define-key function-key-map [right-fringe mouse-3] 'mouse--strip-first-event)
(define-key function-key-map [left-fringe mouse-3] 'mouse--strip-first-event)
diff --git a/lisp/vc/smerge-mode.el b/lisp/vc/smerge-mode.el
index 694d4529b9..3aa7399dd5 100644
--- a/lisp/vc/smerge-mode.el
+++ b/lisp/vc/smerge-mode.el
@@ -385,6 +385,8 @@ smerge-remove-props
(defun smerge-popup-context-menu (event)
"Pop up the Smerge mode context menu under mouse."
(interactive "e")
+ (unless (eq (posn-window (event-end event)) (selected-window))
+ (select-window (posn-window (event-end event))))
(if (and smerge-mode
(save-excursion (posn-set-point (event-end event)) (smerge-check 1)))
(progn
- Re: Context menus and mouse-3,
Juri Linkov <=
- RE: [External] : Re: Context menus and mouse-3, Drew Adams, 2021/07/11
- Re: Context menus and mouse-3, Eli Zaretskii, 2021/07/12
- Re: Context menus and mouse-3, Juri Linkov, 2021/07/12
- RE: [External] : Re: Context menus and mouse-3, Drew Adams, 2021/07/12
- Re: Context menus and mouse-3, Eli Zaretskii, 2021/07/13
- Re: Context menus and mouse-3, Juri Linkov, 2021/07/13
- Re: Context menus and mouse-3, Eli Zaretskii, 2021/07/14
- Re: Context menus and mouse-3, Juri Linkov, 2021/07/14
- Re: Context menus and mouse-3, Eli Zaretskii, 2021/07/15
- Re: Context menus and mouse-3, Juri Linkov, 2021/07/15