From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.devel Subject: Re: Context menus and mouse-3 Date: Mon, 12 Jul 2021 02:38:19 +0300 Organization: LINKOV.NET Message-ID: <87y2acv2tw.fsf@mail.linkov.net> References: <20200914061111.3trmuzhdvv7nwdcc@Ergus> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="22286"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (x86_64-pc-linux-gnu) Cc: philipk@posteo.net, Richard Stallman , spacibba@aol.com, emacs-devel@gnu.org, arthur.miller@live.com, dgutov@yandex.ru, ghe@sdf.org, drew.adams@oracle.com To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Mon Jul 12 01:48:59 2021 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1m2jBy-0005dO-Ck for ged-emacs-devel@m.gmane-mx.org; Mon, 12 Jul 2021 01:48:58 +0200 Original-Received: from localhost ([::1]:41862 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m2jBx-00072K-EV for ged-emacs-devel@m.gmane-mx.org; Sun, 11 Jul 2021 19:48:57 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:45736) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m2jAc-0006DL-GK for emacs-devel@gnu.org; Sun, 11 Jul 2021 19:47:34 -0400 Original-Received: from relay2-d.mail.gandi.net ([217.70.183.194]:63853) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m2jAT-000279-M9; Sun, 11 Jul 2021 19:47:32 -0400 Original-Received: (Authenticated sender: juri@linkov.net) by relay2-d.mail.gandi.net (Postfix) with ESMTPSA id 31C3440007; Sun, 11 Jul 2021 23:47:18 +0000 (UTC) In-Reply-To: (Stefan Monnier's message of "Tue, 15 Sep 2020 09:11:20 -0400") Received-SPF: pass client-ip=217.70.183.194; envelope-from=juri@linkov.net; helo=relay2-d.mail.gandi.net X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:271179 Archived-At: --=-=-= Content-Type: text/plain >> > 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. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=mouse-3-down-context-menu.patch 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 --=-=-=--