From: Po Lu Date: Sun, 3 Apr 2022 01:14:24 +0000 (+0800) Subject: Add user options to move point and scroll window during DND X-Git-Tag: emacs-29.0.90~1931^2~808 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=1694f82e5f91f1ea96604c7c0aee4537fbada765;p=emacs.git Add user options to move point and scroll window during DND * doc/emacs/frames.texi (Drag and Drop): * etc/NEWS: Document new options 'dnd-scroll-margin' and 'dnd-indicate-insertion-point'. * lisp/dnd.el (dnd-protocol-alist): (dnd-open-remote-file-function): (dnd-open-file-other-window): Add right group to defcustoms. (dnd-scroll-margin, dnd-indicate-insertion-point): New user options. (dnd-handle-movement): New function. * lisp/x-dnd.el (x-dnd-handle-xdnd): (x-dnd-handle-motif): Call `dnd-handle-movement' when appropriate. --- diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index 7489344cda9..560870a4ed2 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -1196,6 +1196,18 @@ the variable @code{dnd-open-file-other-window}. The XDND and Motif drag and drop protocols, and the old KDE 1.x protocol, are currently supported. +@vindex dnd-indicate-insertion-point +@vindex dnd-scroll-margin + + It can be difficult to scroll a window or determine where dropped +text will be inserted while dragging text onto an Emacs window. +Setting the option @var{dnd-indicate-insertion-point} to a +non-@code{nil} value makes point move to the location any dropped text +will be inserted when the mouse moves in a window during drag, and +setting @code{dnd-scroll-margin} to an integer value causes a window +to be scrolled if the mouse moves within that many lines of the top +or bottom of the window during drag. + @vindex mouse-drag-and-drop-region Emacs can also optionally drag the region with the mouse into another portion of this or another buffer. To enable that, customize diff --git a/etc/NEWS b/etc/NEWS index 199f07a0334..037a9724d8a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -195,6 +195,11 @@ to another program. If non-nil, this option allows scrolling a window while dragging text around without a scroll wheel. ++++ +** New user options 'dnd-indicate-insertion-point' and 'dnd-scroll-margin'. +These options allow adjusting point and scrolling a window when +dragging items from another program. + +++ ** New function 'command-query'. This function makes its argument command prompt the user for diff --git a/lisp/dnd.el b/lisp/dnd.el index 97e81e9bf11..8b11973eb41 100644 --- a/lisp/dnd.el +++ b/lisp/dnd.el @@ -42,8 +42,7 @@ `((,(purecopy "^file:///") . dnd-open-local-file) ; XDND format. (,(purecopy "^file://") . dnd-open-file) ; URL with host (,(purecopy "^file:") . dnd-open-local-file) ; Old KDE, Motif, Sun - (,(purecopy "^\\(https?\\|ftp\\|file\\|nfs\\)://") . dnd-open-file) - ) + (,(purecopy "^\\(https?\\|ftp\\|file\\|nfs\\)://") . dnd-open-file)) "The functions to call for different protocols when a drop is made. This variable is used by `dnd-handle-one-url' and `dnd-handle-file-name'. @@ -57,7 +56,8 @@ If no match is found, the URL is inserted as text by calling `dnd-insert-text'. The function shall return the action done (move, copy, link or private) if some action was made, or nil if the URL is ignored." :version "22.1" - :type '(repeat (cons (regexp) (function)))) + :type '(repeat (cons (regexp) (function))) + :group 'dnd) (defcustom dnd-open-remote-file-function @@ -73,17 +73,66 @@ Predefined functions are `dnd-open-local-file' and `dnd-open-remote-url'. is the default on MS-Windows. `dnd-open-remote-url' uses `url-handler-mode' and is the default except for MS-Windows." :version "22.1" - :type 'function) + :type 'function + :group 'dnd) (defcustom dnd-open-file-other-window nil "If non-nil, always use `find-file-other-window' to open dropped files." :version "22.1" - :type 'boolean) - + :type 'boolean + :group 'dnd) + +(defcustom dnd-scroll-margin nil + "The scroll margin inside a window underneath the cursor during drag-and-drop. +If the mouse moves this many lines close to the top or bottom of +a window while dragging text, then that window will be scrolled +down and up respectively." + :type '(choice (const :tag "Don't scroll during mouse movement") + (integer :tag "This many lines from window top or bottom")) + :version "29.1" + :group 'dnd) + +(defcustom dnd-indicate-insertion-point nil + "Whether or not point should follow the position of the mouse. +If non-nil, the point of the window underneath the mouse will be +adjusted to reflect where any text will be inserted upon drop +when the mouse moves while receiving a drop from another +program." + :type 'boolean + :version "29.1" + :group 'dnd) ;; Functions +(defun dnd-handle-movement (posn) + "Handle mouse movement to POSN when receiving a drop from another program." + (when dnd-scroll-margin + (ignore-errors + (let* ((row (cdr (posn-col-row posn))) + (window (when (windowp (posn-window posn)) + (posn-window posn))) + (text-height (window-text-height window)) + ;; Make sure it's possible to scroll both up + ;; and down if the margin is too large for the + ;; window. + (margin (min (/ text-height 3) dnd-scroll-margin))) + ;; At 2 lines, the window becomes too small for any + ;; meaningful scrolling. + (unless (<= text-height 2) + (cond + ;; Inside the bottom scroll margin, scroll up. + ((> row (- text-height margin)) + (with-selected-window window + (scroll-up 1))) + ;; Inside the top scroll margin, scroll down. + ((< row margin) + (with-selected-window window + (scroll-down 1)))))))) + (when dnd-indicate-insertion-point + (ignore-errors + (goto-char (posn-point posn))))) + (defun dnd-handle-one-url (window action url) "Handle one dropped url by calling the appropriate handler. The handler is first located by looking at `dnd-protocol-alist'. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index e26703ad848..af9c7b83d97 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -499,7 +499,7 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." ))) (x-send-client-message frame dnd-source frame "XdndStatus" 32 list-to-send) - )) + (dnd-handle-movement (event-start event)))) ((equal "XdndLeave" message) (x-dnd-forget-drop window)) @@ -676,7 +676,8 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." frame "_MOTIF_DRAG_AND_DROP_MESSAGE" 8 - reply))) + reply) + (dnd-handle-movement (event-start event)))) ((eq message-type 'XmOPERATION_CHANGED) (let* ((state (x-dnd-get-state-for-frame frame))