From: "Mattias Engdegård" <mattiase@acm.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 38013@debbugs.gnu.org
Subject: bug#38013: [PATCH] Rectangular region selection with mouse
Date: Sat, 23 Nov 2019 16:17:12 +0100 [thread overview]
Message-ID: <92A2EB6E-A4AC-4D91-AFDE-5F4340DDA2EC@acm.org> (raw)
In-Reply-To: <83y2w6tzja.fsf@gnu.org>
[-- Attachment #1: Type: text/plain, Size: 452 bytes --]
23 nov. 2019 kl. 15.53 skrev Eli Zaretskii <eliz@gnu.org>:
> Fine with me.
Good, mouse-fine-grained-tracking it is then.
> I think this would be better. IME, such small windows eventually
> cause strange and hard to debug bugs, so any measures to make the
> window smaller or eliminate it are welcome.
The window has now been shrunk to almost nothing, and condition-case added for good measure. (Old code in mouse.el left untouched.)
[-- Attachment #2: 0001-Mouse-rectangular-region-selection-bug-38013.patch --]
[-- Type: application/octet-stream, Size: 11701 bytes --]
From 528bf08d5dc448cbeff0db67188be5093eec98a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= <mattiase@acm.org>
Date: Fri, 25 Oct 2019 11:16:39 +0200
Subject: [PATCH] Mouse rectangular region selection (bug#38013)
Make it possible to select a rectangular region using the mouse.
The standard binding is C-M-mouse-1.
* lisp/mouse.el (mouse-scroll-subr): Add ADJUST argument.
(mouse-drag-region-rectangle): New.
* lisp/rect.el (rectangle--reset-point-crutches): New.
(rectangle--reset-crutches): Use 'rectangle--reset-point-crutches'.
* src/xdisp.c (remember_mouse_glyph, syms_of_xdisp):
Add 'mouse-fine-grained-tracking'.
* doc/lispref/commands.texi (Motion Events):
Document 'mouse-fine-grained-tracking'.
* doc/emacs/frames.texi (Mouse Commands):
* doc/emacs/killing.texi (Rectangles):
* etc/NEWS: Document rectangular selection with the mouse.
---
doc/emacs/frames.texi | 4 ++
doc/emacs/killing.texi | 3 +
doc/lispref/commands.texi | 6 ++
etc/NEWS | 3 +
lisp/mouse.el | 114 +++++++++++++++++++++++++++++++++++++-
lisp/rect.el | 8 ++-
src/xdisp.c | 12 ++++
7 files changed, 147 insertions(+), 3 deletions(-)
diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi
index 091c011fb9..f6c2d23913 100644
--- a/doc/emacs/frames.texi
+++ b/doc/emacs/frames.texi
@@ -91,6 +91,10 @@ Mouse Commands
click position; otherwise, set mark at the current value of point and
point at the click position. Save the resulting region in the kill
ring; on a second click, kill it (@code{mouse-save-then-kill}).
+
+@item C-M-mouse-1
+Activate a rectangular region around the text selected by dragging.
+@xref{Rectangles}.
@end table
@findex mouse-set-point
diff --git a/doc/emacs/killing.texi b/doc/emacs/killing.texi
index 80e2868908..ce00cb38a7 100644
--- a/doc/emacs/killing.texi
+++ b/doc/emacs/killing.texi
@@ -732,6 +732,9 @@ Rectangles
and mark values can be interpreted either as a region or as a
rectangle, depending on the command that uses them.
+ A rectangular region can also be marked using the mouse: click and drag
+@kbd{C-M-mouse-1} from one corner of the rectangle to the opposite.
+
@table @kbd
@item C-x r k
Kill the text of the region-rectangle, saving its contents as the
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index 0c848a8025..032f005e9c 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -1661,6 +1661,12 @@ Motion Events
does not generate events for mere motion of the mouse, and these
events do not appear. @xref{Mouse Tracking}.
+@defvar mouse-fine-grained-tracking
+When non-@code{nil}, mouse motion events are generated even for very
+small movements. Otherwise, motion events are not generated as long
+as the mouse cursor remains pointing to the same glyph in the text.
+@end defvar
+
@node Focus Events
@subsection Focus Events
@cindex focus event
diff --git a/etc/NEWS b/etc/NEWS
index ad349b1613..80f0fa5e4e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -585,6 +585,9 @@ region using a given replacement-function in a non-destructive manner
arguments mitigating performance issues when operating on huge
buffers.
++++
+** Dragging 'C-M-mouse-1' now marks rectangular regions.
+
+++
** The command 'delete-indentation' now operates on the active region.
If the region is active, the command joins all the lines in the
diff --git a/lisp/mouse.el b/lisp/mouse.el
index c91760a734..e2be8e6ee3 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -1045,10 +1045,12 @@ mouse-scroll-min-lines
of lines specified by this variable."
:type 'integer)
-(defun mouse-scroll-subr (window jump &optional overlay start)
+(defun mouse-scroll-subr (window jump &optional overlay start adjust)
"Scroll the window WINDOW, JUMP lines at a time, until new input arrives.
If OVERLAY is an overlay, let it stretch from START to the far edge of
the newly visible text.
+ADJUST, if non-nil, is a function, without arguments, to call after
+setting point.
Upon exit, point is at the far edge of the newly visible text."
(cond
((and (> jump 0) (< jump mouse-scroll-min-lines))
@@ -1077,6 +1079,8 @@ mouse-scroll-subr
;; so that we don't mess up the selected window.
(or (eq window (selected-window))
(goto-char opoint))
+ (when adjust
+ (funcall adjust))
(sit-for mouse-scroll-delay)))))
(or (eq window (selected-window))
(goto-char opoint))))
@@ -1960,6 +1964,114 @@ secondary-selection-from-region
(move-overlay mouse-secondary-overlay (region-beginning) (region-end))))
\f
+(defun mouse-drag-region-rectangle (start-event)
+ "Set the region to the rectangle that the mouse is dragged over.
+This must be bound to a button-down mouse event."
+ (interactive "e")
+ (let* ((scroll-margin 0)
+ (start-pos (event-start start-event))
+ (start-posn (event-start start-event))
+ (start-point (posn-point start-posn))
+ (start-window (posn-window start-posn))
+ (start-hscroll (window-hscroll start-window))
+ (start-col (+ (car (posn-col-row start-pos)) start-hscroll))
+ (bounds (window-edges start-window))
+ (top (nth 1 bounds))
+ (bottom (if (window-minibuffer-p start-window)
+ (nth 3 bounds)
+ (1- (nth 3 bounds))))
+ (dragged nil)
+ (old-track-mouse track-mouse)
+ (old-mouse-fine-grained-tracking mouse-fine-grained-tracking)
+ ;; For right-to-left text, columns are counted from the right margin;
+ ;; translate from mouse events, which always count from the left.
+ (adjusted-col (lambda (col)
+ (if (eq (current-bidi-paragraph-direction)
+ 'right-to-left)
+ (- (frame-text-cols) col -1)
+ col)))
+ (map (make-sparse-keymap)))
+ (define-key map [switch-frame] #'ignore)
+ (define-key map [select-window] #'ignore)
+ (define-key map [mouse-movement]
+ (lambda (event)
+ (interactive "e")
+ (unless dragged
+ ;; This is actually a drag.
+ (mouse-minibuffer-check start-event)
+ (deactivate-mark)
+ (posn-set-point start-pos)
+ (rectangle-mark-mode)
+ ;; Only tell rectangle about the exact column if we are possibly
+ ;; beyond end-of-line or in a tab, since the column we got from
+ ;; the mouse position isn't necessarily accurate for use in
+ ;; specifying a rectangle (which uses the `move-to-column'
+ ;; measure).
+ (when (or (eolp) (eq (following-char) ?\t))
+ (let ((col (funcall adjusted-col start-col)))
+ (rectangle--col-pos col 'mark)
+ (rectangle--col-pos col 'point)))
+
+ (setq dragged t))
+
+ (let* ((posn (event-end event))
+ (window (posn-window posn))
+ (hscroll (if (window-live-p window)
+ (window-hscroll window)
+ 0))
+ (mouse-pos (mouse-position))
+ (mouse-col (+ (cadr mouse-pos) hscroll))
+ (mouse-row (cddr mouse-pos))
+ (set-col (lambda ()
+ (if (or (eolp) (eq (following-char) ?\t))
+ (rectangle--col-pos
+ (funcall adjusted-col mouse-col) 'point)
+ (rectangle--reset-point-crutches)))))
+ (if (and (eq window start-window)
+ mouse-row
+ (<= top mouse-row (1- bottom)))
+ ;; Drag inside the same window.
+ (progn
+ (posn-set-point posn)
+ (funcall set-col))
+ ;; Drag outside the window: scroll.
+ (cond
+ ((null mouse-row))
+ ((< mouse-row top)
+ (mouse-scroll-subr
+ start-window (- mouse-row top) nil start-point
+ set-col))
+ ((>= mouse-row bottom)
+ (mouse-scroll-subr
+ start-window (1+ (- mouse-row bottom)) nil start-point
+ set-col)))))))
+ (condition-case err
+ (progn
+ (setq track-mouse t)
+ (setq mouse-fine-grained-tracking t)
+ (set-transient-map
+ map t
+ (lambda ()
+ (setq track-mouse old-track-mouse)
+ (setq mouse-fine-grained-tracking old-mouse-fine-grained-tracking)
+ (when (or (not dragged)
+ (not (mark))
+ (equal (rectangle-dimensions (mark) (point)) '(0 . 1)))
+ ;; No nontrivial region selected; deactivate rectangle mode.
+ (deactivate-mark)))))
+ ;; Clean up in case something went wrong.
+ (error (setq track-mouse old-track-mouse)
+ (setq mouse-fine-grained-tracking old-mouse-fine-grained-tracking)
+ (signal (car err) (cdr err))))))
+
+;; The drag event must be bound to something but does not need any effect,
+;; as everything takes place in `mouse-drag-region-rectangle'.
+;; The click event can be anything; `mouse-set-point' is just a convenience.
+(global-set-key [C-M-down-mouse-1] #'mouse-drag-region-rectangle)
+(global-set-key [C-M-drag-mouse-1] #'ignore)
+(global-set-key [C-M-mouse-1] #'mouse-set-point)
+
+\f
(defcustom mouse-buffer-menu-maxlen 20
"Number of buffers in one pane (submenu) of the buffer menu.
If we have lots of buffers, divide them into groups of
diff --git a/lisp/rect.el b/lisp/rect.el
index 4d4d6146f2..1109786fc5 100644
--- a/lisp/rect.el
+++ b/lisp/rect.el
@@ -133,11 +133,15 @@ rectangle--point-col
(defun rectangle--crutches ()
(cons rectangle--mark-crutches
(window-parameter nil 'rectangle--point-crutches)))
-(defun rectangle--reset-crutches ()
- (kill-local-variable 'rectangle--mark-crutches)
+
+(defun rectangle--reset-point-crutches ()
(if (window-parameter nil 'rectangle--point-crutches)
(setf (window-parameter nil 'rectangle--point-crutches) nil)))
+(defun rectangle--reset-crutches ()
+ (kill-local-variable 'rectangle--mark-crutches)
+ (rectangle--reset-point-crutches))
+
;;; Rectangle operations.
(defun apply-on-rectangle (function start end &rest args)
diff --git a/src/xdisp.c b/src/xdisp.c
index c5676b3e17..507d055fc9 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2491,6 +2491,12 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
enum glyph_row_area area;
int x, y, width, height;
+ if (mouse_fine_grained_tracking)
+ {
+ STORE_NATIVE_RECT (*rect, gx, gy, 1, 1);
+ return;
+ }
+
/* Try to determine frame pixel position and size of the glyph under
frame pixel coordinates X/Y on frame F. */
@@ -34943,6 +34949,12 @@ syms_of_xdisp (void)
may be more familiar to users. */);
display_raw_bytes_as_hex = false;
+ DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
+ doc: /* Non-nil for pixel-wise mouse-movement.
+When nil, mouse-movement events will not be generated as long as the
+mouse stays within the extent of a single glyph (except for images). */);
+ mouse_fine_grained_tracking = false;
+
}
--
2.21.0 (Apple Git-122.2)
next prev parent reply other threads:[~2019-11-23 15:17 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-31 21:55 bug#38013: [PATCH] Rectangular region selection with mouse Mattias Engdegård
2019-11-01 0:12 ` Drew Adams
2019-11-01 7:51 ` Eli Zaretskii
2019-11-01 11:53 ` Mattias Engdegård
2019-11-01 13:17 ` Eli Zaretskii
2019-11-01 13:30 ` Eli Zaretskii
2019-11-03 21:12 ` Mattias Engdegård
2019-11-03 21:51 ` Drew Adams
2019-11-04 9:07 ` martin rudalics
2019-11-04 11:33 ` Mattias Engdegård
2019-11-04 15:25 ` Drew Adams
2019-11-04 18:27 ` martin rudalics
2019-11-04 20:18 ` Mattias Engdegård
2019-11-05 9:35 ` martin rudalics
2019-11-07 17:48 ` Mattias Engdegård
2019-11-07 17:53 ` Drew Adams
2019-11-07 18:27 ` Mattias Engdegård
2019-11-07 19:08 ` martin rudalics
2019-11-07 20:46 ` Drew Adams
2019-11-08 17:33 ` Mattias Engdegård
2019-11-08 18:28 ` martin rudalics
2019-11-09 15:35 ` Mattias Engdegård
2019-11-09 17:54 ` Eli Zaretskii
2019-11-09 19:32 ` Mattias Engdegård
2019-11-09 20:04 ` Eli Zaretskii
2019-11-10 13:49 ` Mattias Engdegård
2019-11-12 14:26 ` Mattias Engdegård
2019-11-12 15:39 ` Drew Adams
2019-11-14 13:56 ` Mattias Engdegård
2019-11-16 12:35 ` Eli Zaretskii
2019-11-17 12:11 ` Mattias Engdegård
2019-11-18 18:08 ` Mattias Engdegård
2019-11-18 19:22 ` Drew Adams
2019-11-18 21:29 ` Juri Linkov
2019-11-19 7:57 ` martin rudalics
2019-11-19 13:57 ` Mattias Engdegård
2019-11-19 15:09 ` Drew Adams
2019-11-19 15:37 ` Mattias Engdegård
2019-11-19 16:08 ` Drew Adams
2019-11-19 16:26 ` Mattias Engdegård
2019-11-19 17:30 ` Eli Zaretskii
2019-11-20 22:38 ` Juri Linkov
2019-11-19 23:07 ` Juri Linkov
2019-11-20 7:57 ` martin rudalics
2019-11-23 11:57 ` Eli Zaretskii
2019-11-23 12:46 ` Mattias Engdegård
2019-11-23 14:53 ` Eli Zaretskii
2019-11-23 15:17 ` Mattias Engdegård [this message]
2019-11-27 14:04 ` Mattias Engdegård
2019-11-10 3:48 ` Richard Stallman
2019-11-01 13:23 ` martin rudalics
[not found] <<C2CEADBB-4388-45A5-9D4D-8963314B2913@acm.org>
[not found] ` <<83v9s3lo5f.fsf@gnu.org>
[not found] ` <<75EC4FBC-F636-4D75-BAC4-982D85188794@acm.org>
[not found] ` <<9b9222ad-ead7-d0a0-0602-780d0680f070@gmx.at>
[not found] ` <<DEA04CF5-72AC-4251-B10B-06291BDAECC2@acm.org>
[not found] ` <<6bf229f4-c22f-c3c2-5158-5235f908de3c@gmx.at>
[not found] ` <<A13CC15C-D255-4A38-B8EA-5FE818BB45D5@acm.org>
[not found] ` <<8ec84837-172c-1ce5-cab0-b4c96a86274e@gmx.at>
[not found] ` <<411EAB4E-B666-4263-8514-5F47391268B1@acm.org>
[not found] ` <<2df02c1f-fea4-f764-eba6-fd67de581755@gmx.at>
[not found] ` <<B6A6755E-2981-4369-9A6B-A0E752C69A77@acm.org>
[not found] ` <<3b74a108-28e3-fd01-64a5-7c4302e3d979@gmx.at>
[not found] ` <<9A9D13F2-1F4F-4DD4-B92F-96FC4D91DFBD@acm.org>
[not found] ` <<83pni17x5b.fsf@gnu.org>
[not found] ` <<8B95D2D3-8E00-45BF-B57D-EFD49D79EB6A@acm.org>
[not found] ` <<83bltk95p7.fsf@gnu.org>
[not found] ` <<60DD9D65-C3F0-470E-8489-B333E1889D32@acm.org>
[not found] ` <<83ftio6lsy.fsf@gnu.org>
[not found] ` <<290E5E66-964B-4E29-B141-166447AD5556@acm.org>
[not found] ` <<175E5B2E-2256-4FCD-AA8E-9E5BC6DE7907@acm.org>
[not found] ` <<7d94fa94-94e4-46dc-8df0-c40ccf052ee9@default>
[not found] ` <<87imngub40.fsf@mail.linkov.net>
[not found] ` <<60fa6496-c057-b69d-21c1-3b1de85b4b9f@gmx.at>
[not found] ` <<DE4EC019-FA36-434E-882C-D80192512DDB@acm.org>
[not found] ` <<9302a9ac-e64c-41ed-898b-24d59465fba4@default>
[not found] ` <<EACDBDF2-FB23-475A-BCE9-3447DECBABC8@acm.org>
[not found] ` <<ba3f1c42-91a9-4985-9376-6a84196167e8@default>
[not found] ` <<83lfsb22pb.fsf@gnu.org>
2019-11-19 18:32 ` Drew Adams
2019-11-19 19:24 ` Eli Zaretskii
[not found] <<<C2CEADBB-4388-45A5-9D4D-8963314B2913@acm.org>
[not found] ` <<<83v9s3lo5f.fsf@gnu.org>
[not found] ` <<<75EC4FBC-F636-4D75-BAC4-982D85188794@acm.org>
[not found] ` <<<9b9222ad-ead7-d0a0-0602-780d0680f070@gmx.at>
[not found] ` <<<DEA04CF5-72AC-4251-B10B-06291BDAECC2@acm.org>
[not found] ` <<<6bf229f4-c22f-c3c2-5158-5235f908de3c@gmx.at>
[not found] ` <<<A13CC15C-D255-4A38-B8EA-5FE818BB45D5@acm.org>
[not found] ` <<<8ec84837-172c-1ce5-cab0-b4c96a86274e@gmx.at>
[not found] ` <<<411EAB4E-B666-4263-8514-5F47391268B1@acm.org>
[not found] ` <<<2df02c1f-fea4-f764-eba6-fd67de581755@gmx.at>
[not found] ` <<<B6A6755E-2981-4369-9A6B-A0E752C69A77@acm.org>
[not found] ` <<<3b74a108-28e3-fd01-64a5-7c4302e3d979@gmx.at>
[not found] ` <<<9A9D13F2-1F4F-4DD4-B92F-96FC4D91DFBD@acm.org>
[not found] ` <<<83pni17x5b.fsf@gnu.org>
[not found] ` <<<8B95D2D3-8E00-45BF-B57D-EFD49D79EB6A@acm.org>
[not found] ` <<<83bltk95p7.fsf@gnu.org>
[not found] ` <<<60DD9D65-C3F0-470E-8489-B333E1889D32@acm.org>
[not found] ` <<<83ftio6lsy.fsf@gnu.org>
[not found] ` <<<290E5E66-964B-4E29-B141-166447AD5556@acm.org>
[not found] ` <<<175E5B2E-2256-4FCD-AA8E-9E5BC6DE7907@acm.org>
[not found] ` <<<7d94fa94-94e4-46dc-8df0-c40ccf052ee9@default>
[not found] ` <<<87imngub40.fsf@mail.linkov.net>
[not found] ` <<<60fa6496-c057-b69d-21c1-3b1de85b4b9f@gmx.at>
[not found] ` <<<DE4EC019-FA36-434E-882C-D80192512DDB@acm.org>
[not found] ` <<<9302a9ac-e64c-41ed-898b-24d59465fba4@default>
[not found] ` <<<EACDBDF2-FB23-475A-BCE9-3447DECBABC8@acm.org>
[not found] ` <<<ba3f1c42-91a9-4985-9376-6a84196167e8@default>
[not found] ` <<<83lfsb22pb.fsf@gnu.org>
[not found] ` <<dc319e8e-42b3-4db8-b8d4-1580e6397174@default>
[not found] ` <<83d0dn1xfd.fsf@gnu.org>
2019-11-19 19:34 ` Drew Adams
2019-11-19 19:48 ` Eli Zaretskii
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=92A2EB6E-A4AC-4D91-AFDE-5F4340DDA2EC@acm.org \
--to=mattiase@acm.org \
--cc=38013@debbugs.gnu.org \
--cc=eliz@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).