all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
To: rudalics@gmx.at
Cc: eliz@gnu.org, tak.kunihiro@gmail.com, agrambot@gmail.com,
	emacs-devel@gnu.org
Subject: Re: mouse-drag-and-drop-region
Date: Mon, 27 Nov 2017 22:11:26 +0900 (JST)	[thread overview]
Message-ID: <20171127.221126.1551780406743300719.tkk@misasa.okayama-u.ac.jp> (raw)
In-Reply-To: <5A17E03C.4000304@gmx.at>

I re-revised mouse-drag-and-drop-region.  I'm sending replay to
https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00589.html,
ChangeLog, and patch.

* ChangeLog

2017-11-27 Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>

        Improve comments and have three new options

        * lisp/mouse.el (mouse-drag-and-drop-region): Make usage of tooltip option.  Have option to make dragging cut among buffers.
        (mouse-drag-and-drop-region-cut-when-buffers-differ): New variable.  If non-nil, text is cut instead of copied when dragged among buffers.
        (mouse-drag-and-drop-region-show-tooltip): New variable.  If non-nil, text is shown by tooltip in a graphic display.
        (mouse-drag-and-drop-region-face): New variable for face.  The face is used to highlight the original text.

* Replay

> instead of perusing the secondary overlay, you don't use your own
> overlay to indicate start and end of the text you cut or copy.  When
> done with the operation or when an error occurs during dragging, you
> simply remove that overlay.  In addition, you can define a face the
> user can customize in order to highlight that overlay.

OK.  That is a good idea.  I got rid of usage of secondary-overlay.  I
define a new variable mouse-drag-and-drop-region-face.

>> How to show insert point?
>
> I think that by default the insert point should be shown by the
> mouse cursor alone.  Optionally, I see no problem showing the normal
> cursor just as `mouse-drag-region' does, maybe with some
> customizable cursor type (I think "bar" would give a better feeling
> than "box").

OK.  Only set point by mouse-set-point when
mouse-drag-and-drop-region-show-tooltip is non-nil with changing
cursor type.  I also changed the default of
mouse-drag-and-drop-region-show-tooltip to nil to be more stable
against accident during dragging.

> More precisely, you should wrap 'track-mouse' and whatever you do
> after it terminates in a 'condition-case' form and in the error part
> restore everything to the saved values.  Like so:
>
> (... ; save the state here
>  (condition-case nil
>      (progn
>        (track-mouse
> 	 )
>        )
>    (error ... ; restore the state here
> 	  )))
>
> If you have any problems coding that, please ask.

Even track-mouse is sandwiched by condition-case, I cannot catch a
error typing during dragging.  However, as inferred already, when
mouse-drag-and-drop-region-show-tooltip is nil, it is more stable even
typing key during dragging.


* Patch

diff --git a/lisp/mouse.el b/lisp/mouse.el
old mode 100644
new mode 100755
index 17d1732..b81d56e
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -2361,6 +2361,29 @@ text is copied instead of being cut."
   :version "26.1"
   :group 'mouse)
 
+(defcustom mouse-drag-and-drop-region-cut-when-buffers-differ nil
+  "If non-nil, cut text also when source and destination buffers differ.
+If this option is nil, `mouse-drag-and-drop-region' will leave
+the text in the source buffer alone when dropping it in a
+different buffer.  If this is non-nil, it will cut the text just
+as it does when dropping text in the source buffer."
+  :type 'boolean
+  :version "26.1"
+  :group 'mouse)
+
+(defcustom mouse-drag-and-drop-region-show-tooltip nil
+  "If non-nil, text is shown by a tooltip in a graphic display.
+If this option is non-nil, point is set to where the mouse cursor
+is during dragging and the original text is highlighted by face
+`mouse-drag-and-drop-region-face'."
+  :type 'boolean
+  :version "26.1"
+  :group 'mouse)
+
+(defvar mouse-drag-and-drop-region-face 'region
+  "Face to highlight the original text during dragging.
+See also `mouse-drag-and-drop-region-show-tooltip'.")
+
 (defun mouse-drag-and-drop-region (event)
   "Move text in the region to point where mouse is dragged to.
 The transportation of text is also referred as `drag and drop'.
@@ -2369,66 +2392,171 @@ modifier key was pressed when dropping, and the value of the
 variable `mouse-drag-and-drop-region' is that modifier, the text
 is copied instead of being cut."
   (interactive "e")
-  (require 'tooltip)
-  (let ((start (region-beginning))
-        (end (region-end))
-        (point (point))
-        (buffer (current-buffer))
-        (window (selected-window))
-        value-selection)
+  (let* ((mouse-drag-and-drop-region-show-tooltip
+          (and mouse-drag-and-drop-region-show-tooltip
+               (display-multi-frame-p)
+               (require 'tooltip)))
+         (start (region-beginning))
+         (end (region-end))
+         (point (point))
+         (buffer (current-buffer))
+         (window (selected-window))
+         (cursor-type cursor-type)
+         (text-from-read-only buffer-read-only)
+         (mouse-drag-and-drop-overlay
+          (make-overlay start end))
+         point-to-paste
+         point-to-paste-read-only
+         window-to-paste
+         no-modifier-on-drop
+         drag-but-negligible
+         clicked
+         value-selection)   ; This remains nil when event was "click".
+
+    ;; FIXME: Handle error such as hitting C-g while dragging.  See
+    ;; https://lists.gnu.org/archive/html/emacs-devel/2017-11/msg00486.html
     (track-mouse
-      ;; When event was click instead of drag, skip loop
+      ;; When event was "click" instead of "drag", skip loop.
       (while (progn
                (setq event (read-event))
                (or (mouse-movement-p event)
                    ;; Handle `mouse-autoselect-window'.
                    (eq (car-safe event) 'select-window)))
-        (unless value-selection ; initialization
-          (delete-overlay mouse-secondary-overlay)
+        ;; Obtain the dragged text in region.  When the loop was
+        ;; skipped, value-selection remains nil.
+        (unless value-selection
           (setq value-selection (buffer-substring start end))
-          (move-overlay mouse-secondary-overlay start end)) ; (deactivate-mark)
-        (ignore-errors (deactivate-mark) ; care existing region in other window
-                       (mouse-set-point event)
-                       (tooltip-show value-selection)))
-      (tooltip-hide))
-    ;; Do not modify buffer under mouse when "event was click",
-    ;;                                       "drag negligible", or
-    ;;                                       "drag to read-only".
-    (if (or (equal (mouse-posn-property (event-end event) 'face) 'region) ; "event was click"
-            (member 'secondary-selection ; "drag negligible"
-                    (mapcar (lambda (xxx) (overlay-get xxx 'face))
-                            (overlays-at (posn-point (event-end event)))))
-            buffer-read-only)
-        ;; Do not modify buffer under mouse.
-        (cond
-         ;; "drag negligible" or "drag to read-only", restore region.
-         (value-selection
-          (select-window window) ; In case miss drag to other window
-          (goto-char point)
+
+          ;; Check if selected text is read-only.
+          (dolist (index (number-sequence start end))
+            ;; (add-text-properties (region-beginning) (region-end) '(read-only t))
+            (setq text-from-read-only (or text-from-read-only
+                                          (get-text-property index 'read-only)))))
+        (ignore-errors
+          (setq window-to-paste (posn-window (event-end event)))
+          (setq point-to-paste (posn-point (event-end event)))
+
+          ;; Check if point under mouse is read-only.
+          (save-window-excursion
+            (select-window window-to-paste)
+            ;; (add-text-properties (region-beginning) (region-end) '(read-only t))
+            (setq point-to-paste-read-only
+                  (or buffer-read-only
+                      (get-text-property point-to-paste 'read-only))))
+
+          ;; Check if "drag but negligible".  Operation "drag but
+          ;; negligible" is defined as drag-and-drop the text to
+          ;; the original region.  When modifier is pressed, the
+          ;; text will be inserted to inside of the original
+          ;; region.
+          (setq drag-but-negligible
+                (member mouse-drag-and-drop-region-face
+                        (mapcar (lambda (xxx) (overlay-get xxx 'face))
+                                (overlays-at point-to-paste))))
+
+          ;; Show tooltip.
+          (when mouse-drag-and-drop-region-show-tooltip
+            (overlay-put mouse-drag-and-drop-overlay
+                         'face mouse-drag-and-drop-region-face)
+            (deactivate-mark)   ; Maintain region in other window.
+            (mouse-set-point event)
+            (setq cursor-type (if (or point-to-paste-read-only
+                                      drag-but-negligible)
+                                  'hollow
+                                'bar))
+            (if (and (not drag-but-negligible)
+                     (not point-to-paste-read-only))
+                (tooltip-show value-selection)
+              (tooltip-hide)))))
+      ;; Hide a tooltip.
+      (when mouse-drag-and-drop-region-show-tooltip (tooltip-hide)))
+    
+
+    ;; Check if modifier was pressed on drop.
+    (setq no-modifier-on-drop
+          (not (member mouse-drag-and-drop-region (event-modifiers event))))
+
+    ;; Check if event was "click".
+    ;; (setq clicked (equal (mouse-posn-property (event-end event) 'face) 'region))
+    (setq clicked (not value-selection))
+
+    ;; Do not modify any buffers when event is "click",
+    ;; "drag but negligible", or "drag to read-only".
+    (let* ((mouse-drag-and-drop-region-cut-when-buffers-differ
+            (if no-modifier-on-drop
+                mouse-drag-and-drop-region-cut-when-buffers-differ
+              (not mouse-drag-and-drop-region-cut-when-buffers-differ)))
+           (wanna-paste-to-same-buffer (equal (window-buffer window-to-paste) buffer))
+           (wanna-cut-on-same-buffer (and wanna-paste-to-same-buffer
+                                          no-modifier-on-drop))
+           (wanna-cut-on-other-buffer (and (not wanna-paste-to-same-buffer)
+                                           mouse-drag-and-drop-region-cut-when-buffers-differ))
+           (cannot-paste (or point-to-paste-read-only
+                             (when (or wanna-cut-on-same-buffer
+                                       wanna-cut-on-other-buffer)
+                               text-from-read-only))))
+
+      (cond
+       ;; Move point within region.
+       (clicked
+        (deactivate-mark)
+        (mouse-set-point event))
+       ;; Undo operation. Set back the original text as region.
+       ((or (and drag-but-negligible
+                 no-modifier-on-drop)
+            cannot-paste)
+        ;; Inform user either source or destination buffer cannot be modified.
+        (when (and (not drag-but-negligible)
+                   cannot-paste)
+          (message "Buffer is read-only"))
+
+        ;; Select source window back and restore region.
+        ;; (set-window-point window point)
+        (select-window window)
+        (goto-char point)
+        (setq deactivate-mark nil)
+        (activate-mark))
+       ;; Modify buffers.
+       (t
+        ;; * DESTINATION BUFFER::
+        ;; Insert the text to destination buffer under mouse.
+        (select-window window-to-paste)
+        (goto-char point-to-paste)
+        (push-mark)
+        (insert value-selection)
+        ;; On success, set the text as region on destination buffer.
+        (when (not (equal (mark) (point)))
           (setq deactivate-mark nil)
           (activate-mark))
-         ;; "event was click"
-         (t
-          (deactivate-mark)
-          (mouse-set-point event)))
-      ;; Modify buffer under mouse by inserting text.
-      (push-mark)
-      (insert value-selection)
-      (when (not (equal (mark) (point))) ; on success insert
-        (setq deactivate-mark nil)
-        (activate-mark)) ; have region on destination
-      ;; Take care of initial region on source.
-      (if (equal (current-buffer) buffer) ; when same buffer
-          (let (deactivate-mark) ; remove text
-            (unless (member mouse-drag-and-drop-region (event-modifiers event))
-              (kill-region (overlay-start mouse-secondary-overlay)
-                           (overlay-end mouse-secondary-overlay))))
-        (let ((window1 (selected-window))) ; when beyond buffer
-          (select-window window)
-          (goto-char point) ; restore point on source window
-          (activate-mark) ; restore region
-          (select-window window1))))
-    (delete-overlay mouse-secondary-overlay)))
+
+        ;; * SOURCE BUFFER::
+        ;; Set back the original text as region or delete the original
+        ;; text, on source buffer.
+        (if wanna-paste-to-same-buffer
+            ;; When source buffer and destination buffer are the same,
+            ;; remove the original text.
+            (when no-modifier-on-drop
+              (let (deactivate-mark)
+                (delete-region (overlay-start mouse-drag-and-drop-overlay)
+                               (overlay-end mouse-drag-and-drop-overlay))))
+          ;; When source buffer and destination buffer are different,
+          ;; keep (set back the original text as region) or remove the
+          ;; original text.
+          (select-window window)   ; Select window with source buffer.
+          (goto-char point) ; Move point to the original text on source buffer.
+
+          (if mouse-drag-and-drop-region-cut-when-buffers-differ
+              ;; Remove the dragged text from source buffer like
+              ;; operation `cut'.
+              (delete-region (overlay-start mouse-drag-and-drop-overlay)
+                             (overlay-end mouse-drag-and-drop-overlay))
+            ;; Set back the dragged text as region on source buffer
+            ;; like operation `copy'.
+            (activate-mark))
+          (select-window window-to-paste)))))
+
+    ;; Clean up.
+    (delete-overlay mouse-drag-and-drop-overlay)))
 \f
 
 ;;; Bindings for mouse commands.



  reply	other threads:[~2017-11-27 13:11 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-14  9:54 mouse-drag-and-drop-region martin rudalics
2017-11-14 17:01 ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-14 18:29   ` mouse-drag-and-drop-region martin rudalics
2017-11-14 20:17 ` mouse-drag-and-drop-region Alex
2017-11-15  9:22   ` mouse-drag-and-drop-region martin rudalics
2017-11-15 18:22     ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-15 18:50       ` mouse-drag-and-drop-region martin rudalics
2017-11-15 20:01         ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-16  9:04           ` mouse-drag-and-drop-region martin rudalics
2017-11-15 19:46     ` mouse-drag-and-drop-region Alex
2017-11-15 20:15       ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-15 22:03         ` mouse-drag-and-drop-region Alex
2017-11-16 15:54           ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-17  6:33             ` mouse-drag-and-drop-region Alex
2017-11-17  7:33               ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-17 15:58                 ` mouse-drag-and-drop-region Stefan Monnier
2017-11-17 16:39                   ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-17 22:44                     ` mouse-drag-and-drop-region Stefan Monnier
2017-11-18  7:54                       ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-18 14:36                         ` mouse-drag-and-drop-region Stefan Monnier
2017-11-18 15:04                           ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-18 15:49                             ` mouse-drag-and-drop-region Stefan Monnier
2017-11-18  6:48                 ` mouse-drag-and-drop-region Alex
2017-11-18  9:07                   ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-18 21:58                     ` mouse-drag-and-drop-region Alex
2017-11-19 15:27                       ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-17  8:53               ` mouse-drag-and-drop-region martin rudalics
2017-11-18  6:49                 ` mouse-drag-and-drop-region Alex
2017-11-16  9:04       ` mouse-drag-and-drop-region martin rudalics
2017-11-17  6:02         ` mouse-drag-and-drop-region Alex
2017-11-17  8:53           ` mouse-drag-and-drop-region martin rudalics
2017-11-15 20:22   ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-16  0:28 ` mouse-drag-and-drop-region Tak Kunihiro
2017-11-16  9:11   ` mouse-drag-and-drop-region martin rudalics
2017-11-20 13:29     ` mouse-drag-and-drop-region Tak Kunihiro
2017-11-20 16:03       ` mouse-drag-and-drop-region Drew Adams
2017-11-20 16:09         ` mouse-drag-and-drop-region Alan Schmitt
2017-11-20 17:34         ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-20 18:17         ` mouse-drag-and-drop-region Paul Eggert
2017-11-21  9:24       ` mouse-drag-and-drop-region martin rudalics
2017-11-21 13:09         ` mouse-drag-and-drop-region Stefan Monnier
2017-11-21 14:05           ` mouse-drag-and-drop-region martin rudalics
2017-11-21 19:07             ` mouse-drag-and-drop-region Stefan Monnier
2017-11-22  8:26               ` mouse-drag-and-drop-region martin rudalics
2017-11-22 21:20                 ` mouse-drag-and-drop-region Stefan Monnier
2017-11-23  7:46                   ` mouse-drag-and-drop-region martin rudalics
2017-11-23 14:00                     ` mouse-drag-and-drop-region Stefan Monnier
2017-11-23 16:09                     ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-24  9:02                       ` mouse-drag-and-drop-region martin rudalics
2017-11-24  9:19                         ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-24  9:41                           ` mouse-drag-and-drop-region martin rudalics
2017-11-24 13:25                             ` mouse-drag-and-drop-region Stefan Monnier
2017-11-26 10:24                               ` mouse-drag-and-drop-region martin rudalics
2017-11-24 13:45                             ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-26 10:24                               ` mouse-drag-and-drop-region martin rudalics
2017-11-26 15:54                                 ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-27  8:48                                   ` mouse-drag-and-drop-region martin rudalics
2017-11-27 15:59                                     ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-21 15:45         ` mouse-drag-and-drop-region Eli Zaretskii
2017-11-22  8:22           ` mouse-drag-and-drop-region martin rudalics
2017-11-21 18:52         ` mouse-drag-and-drop-region Robert Weiner
2017-11-22  8:22           ` mouse-drag-and-drop-region martin rudalics
2017-11-23 23:28         ` mouse-drag-and-drop-region Tak Kunihiro
2017-11-24  9:02           ` mouse-drag-and-drop-region martin rudalics
2017-11-27 13:11             ` Tak Kunihiro [this message]
2017-11-28  8:50               ` mouse-drag-and-drop-region martin rudalics
2017-12-01 14:16                 ` mouse-drag-and-drop-region Tak Kunihiro
2017-12-02 10:16                   ` mouse-drag-and-drop-region martin rudalics
2017-12-03 10:06                     ` mouse-drag-and-drop-region martin rudalics
2017-12-03 13:36                       ` mouse-drag-and-drop-region martin rudalics
2017-12-05  4:57                       ` mouse-drag-and-drop-region Tak Kunihiro
2017-12-05  8:53                         ` mouse-drag-and-drop-region martin rudalics
2017-12-06  9:29                           ` mouse-drag-and-drop-region Tak Kunihiro
2017-12-07  9:26                             ` mouse-drag-and-drop-region martin rudalics
2017-12-07 21:45                               ` mouse-drag-and-drop-region Tak Kunihiro
2017-12-08 10:12                                 ` mouse-drag-and-drop-region martin rudalics
2017-12-08 16:14                                   ` mouse-drag-and-drop-region Robert Weiner
2017-12-09 10:35                                     ` mouse-drag-and-drop-region martin rudalics
2017-12-14 23:14                                       ` mouse-drag-and-drop-region Tak Kunihiro
2017-12-15  8:50                                         ` mouse-drag-and-drop-region martin rudalics
2017-12-15 13:25                                           ` mouse-drag-and-drop-region martin rudalics
2017-12-16  2:07                                             ` mouse-drag-and-drop-region Tak Kunihiro
2017-12-16  9:42                                               ` mouse-drag-and-drop-region martin rudalics
2017-12-17  4:40                                                 ` mouse-drag-and-drop-region Tak Kunihiro
2017-12-17 10:44                                                   ` mouse-drag-and-drop-region martin rudalics
2017-12-21  1:36                                                     ` mouse-drag-and-drop-region Tak Kunihiro
2017-12-22  8:43                                                       ` mouse-drag-and-drop-region martin rudalics
2017-12-22  9:25                                                       ` mouse-drag-and-drop-region Eli Zaretskii
2017-12-22 17:57                                                         ` mouse-drag-and-drop-region martin rudalics

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

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171127.221126.1551780406743300719.tkk@misasa.okayama-u.ac.jp \
    --to=tkk@misasa.okayama-u.ac.jp \
    --cc=agrambot@gmail.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    --cc=rudalics@gmx.at \
    --cc=tak.kunihiro@gmail.com \
    /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 external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.