Improve the documentation of the XDS support
* doc/lispref/frames.texi (Drag and Drop): Rephrase and rearrange the documentation of XDS support. Add indexing. Document 'x-dnd-save-direct' and 'x-dnd-save-direct-immediately'. Original patch from Po Lu <luangruo@yahoo.com>. * lisp/x-dnd.el (x-dnd-types-alist, x-dnd-test-function) (x-dnd-default-test-function, x-dnd-direct-save-function): Doc fixes. (x-dnd-save-direct, x-dnd-save-direct-immediately): Rename the second argument to FILENAME. Doc fix.
This commit is contained in:
parent
14d1c00e80
commit
08cda286c3
2 changed files with 131 additions and 73 deletions
|
@ -4112,7 +4112,7 @@ has the same meaning as the @var{action} argument to
|
||||||
Emacs implements receiving text and URLs individually for each
|
Emacs implements receiving text and URLs individually for each
|
||||||
window system, and does not by default support receiving other kinds
|
window system, and does not by default support receiving other kinds
|
||||||
of data as drops. To support receiving other kinds of data, use the
|
of data as drops. To support receiving other kinds of data, use the
|
||||||
X-specific interface described below:
|
X-specific interface described below.
|
||||||
|
|
||||||
@vindex x-dnd-test-function
|
@vindex x-dnd-test-function
|
||||||
@vindex x-dnd-known-types
|
@vindex x-dnd-known-types
|
||||||
|
@ -4141,29 +4141,71 @@ depending on the specific drag-and-drop protocol being used. For
|
||||||
example, the data type used for plain text may be either
|
example, the data type used for plain text may be either
|
||||||
@code{"STRING"} or @code{"text/plain"}.
|
@code{"STRING"} or @code{"text/plain"}.
|
||||||
|
|
||||||
|
@cindex XDS
|
||||||
|
@cindex direct save protocol
|
||||||
@vindex x-dnd-direct-save-function
|
@vindex x-dnd-direct-save-function
|
||||||
@c FIXME: This description is overly-complicated and confusing. In
|
When Emacs runs on X window system, it supports the X Direct Save
|
||||||
@c particular, the two calls to the function basically sound
|
(@acronym{XDS}) protocol, which allows users to save a file by
|
||||||
@c identical, so it is unclear how should the function distinguish
|
dragging and dropping it onto an Emacs window, such as a Dired window.
|
||||||
@c between the first and the second one. The description of who asks
|
To comply with the unique requirements of @acronym{XDS}, these
|
||||||
@c whom to do what is also very hard to understand. Needs rewording,
|
drag-and-drop requests are processed specially: instead of being
|
||||||
@c and needs shorter sentences. Perhaps examples could help.
|
handled according to @code{x-dnd-types-alist}, they are handled by the
|
||||||
However, @code{x-dnd-types-alist} does not handle a special kind of
|
@dfn{direct-save function} that is the value of the variable
|
||||||
drop sent by a program that wants Emacs to tell it where to save a
|
@code{x-dnd-direct-save-function}. The value should be a function of
|
||||||
file in a specific location determined by the user. These drops are
|
two arguments, @var{need-name} and @var{filename}. The @acronym{XDS}
|
||||||
instead handled by a function that is the value of the variable
|
protocol uses a two-step procedure for dragging files:
|
||||||
@code{x-dnd-direct-save-function}. This function should accept two arguments.
|
|
||||||
If the first argument is non-@code{nil}, then the second argument is a
|
@enumerate 1
|
||||||
file name to save (with leading directories) that the other
|
@item
|
||||||
program recommends, and the
|
The application from which the file is dragged asks Emacs to provide
|
||||||
function should return the full file name under which it should be
|
the full file name under which to save the file. For this purpose,
|
||||||
saved. After the function completes, Emacs will ask the other program
|
the direct-save function is called with its first argument
|
||||||
to save the file under the name that was returned, and if the file was
|
@var{need-name} non-@code{nil}, and the second argument @var{filename}
|
||||||
successfully saved, call the function again with the first argument
|
set to the basename of the file to be saved. It should return the
|
||||||
set to a non-@code{nil} value and the second argument set to the file
|
fully-expanded absolute file name under which to save the file. For
|
||||||
name that was returned. The function should then perform whatever
|
example, if a file is dragged to a Dired window, the natural directory
|
||||||
action is appropriate (i.e., opening the file or refreshing a
|
for the file is the directory of the file shown at location of the
|
||||||
directory listing.)
|
drop. If saving the file is not possible for some reason, the
|
||||||
|
function should return @code{nil}, which will cancel the drag-and-drop
|
||||||
|
operation.
|
||||||
|
|
||||||
|
@item
|
||||||
|
The application from which the file is dragged saves the file under
|
||||||
|
the name returned by the first call to the direct-save function. If
|
||||||
|
it succeeds in saving the file, the direct-save function is called
|
||||||
|
again, this time with the first argument @var{need-name} set to
|
||||||
|
@code{nil} and the second argument @var{filename} set to the full
|
||||||
|
absolute name of the saved file. The function is then expected to do
|
||||||
|
whatever is needed given the fact that file was saved. For example,
|
||||||
|
Dired should update the directory on display by showing the new file
|
||||||
|
there.
|
||||||
|
@end enumerate
|
||||||
|
|
||||||
|
The default value of @code{x-dnd-direct-save-function} is
|
||||||
|
@code{x-dnd-save-direct}.
|
||||||
|
|
||||||
|
@defun x-dnd-save-direct need-name filename
|
||||||
|
When called with the @var{need-name} argument non-@code{nil}, this
|
||||||
|
function prompts the user for the absolute file name under which it
|
||||||
|
should be saved. If the specified file already exists, it
|
||||||
|
additionally asks the user whether to overwrite it, and returns the
|
||||||
|
absolute file name only if the user confirms the overwriting.
|
||||||
|
|
||||||
|
When called with the @var{need-name} argument @code{nil}, it reverts
|
||||||
|
the Dired listing if the current buffer is in Dired mode or one of its
|
||||||
|
descendants, and otherwise visits the file by calling @code{find-file}
|
||||||
|
(@pxref{Visiting Functions}).
|
||||||
|
@end defun
|
||||||
|
|
||||||
|
@defun x-dnd-save-direct-immediately need-name filename
|
||||||
|
This function works like @code{x-dnd-save-direct}, but when called
|
||||||
|
with its @var{need-name} argument non-@code{nil}, it doesn't prompt
|
||||||
|
the user for the full name of the file to be saved; instead, it
|
||||||
|
returns its argument @var{filename} expanded against the current
|
||||||
|
buffer's default directory (@pxref{File Name Expansion}). (It still
|
||||||
|
asks for confirmation if a file by that name already exists in the
|
||||||
|
default directory.)
|
||||||
|
@end defun
|
||||||
|
|
||||||
@cindex initiating drag-and-drop
|
@cindex initiating drag-and-drop
|
||||||
On capable window systems, Emacs also supports dragging contents
|
On capable window systems, Emacs also supports dragging contents
|
||||||
|
|
116
lisp/x-dnd.el
116
lisp/x-dnd.el
|
@ -34,20 +34,20 @@
|
||||||
|
|
||||||
;;; Customizable variables
|
;;; Customizable variables
|
||||||
(defcustom x-dnd-test-function #'x-dnd-default-test-function
|
(defcustom x-dnd-test-function #'x-dnd-default-test-function
|
||||||
"The function drag and drop uses to determine if to accept or reject a drop.
|
"Function to be used by drag-and-drop to determine whether to accept a drop.
|
||||||
The function takes three arguments, WINDOW, ACTION and TYPES.
|
The function takes three arguments: WINDOW, ACTION, and TYPES.
|
||||||
WINDOW is where the mouse is when the function is called. WINDOW
|
WINDOW is where the window under the mouse is when the function is called.
|
||||||
may be a frame if the mouse isn't over a real window (i.e. menu
|
WINDOW may be a frame if the mouse isn't over a real window (e.g., menu
|
||||||
bar, tool bar or scroll bar). ACTION is the suggested action
|
bar, tool bar, scroll bar, etc.).
|
||||||
from the drag and drop source, one of the symbols move, copy,
|
ACTION is the suggested action from the drag and drop source, one of the
|
||||||
link or ask. TYPES is a vector of available types for the drop.
|
symbols `move', `copy', `link' or `ask'.
|
||||||
|
TYPES is a vector of available types for the drop.
|
||||||
Each element of TYPE should either be a string (containing the
|
Each element of TYPES should either be a string (containing the
|
||||||
name of the type's X atom), or a symbol, whose name will be used.
|
name of the type's X atom), or a symbol, whose name will be used.
|
||||||
|
|
||||||
The function shall return nil to reject the drop or a cons with
|
The function shall return nil to reject the drop or a cons with
|
||||||
two values, the wanted action as car and the wanted type as cdr.
|
two values, the wanted action as `car' and the wanted type as `cdr'.
|
||||||
The wanted action can be copy, move, link, ask or private.
|
The wanted action can be `copy', `move', `link', `ask' or `private'.
|
||||||
|
|
||||||
The default value for this variable is `x-dnd-default-test-function'."
|
The default value for this variable is `x-dnd-default-test-function'."
|
||||||
:version "22.1"
|
:version "22.1"
|
||||||
|
@ -70,14 +70,18 @@ The default value for this variable is `x-dnd-default-test-function'."
|
||||||
(,(purecopy "DndTypeFile") . x-dnd-handle-offix-file)
|
(,(purecopy "DndTypeFile") . x-dnd-handle-offix-file)
|
||||||
(,(purecopy "DndTypeFiles") . x-dnd-handle-offix-files)
|
(,(purecopy "DndTypeFiles") . x-dnd-handle-offix-files)
|
||||||
(,(purecopy "DndTypeText") . dnd-insert-text))
|
(,(purecopy "DndTypeText") . dnd-insert-text))
|
||||||
"Which function to call to handle a drop of that type.
|
"Functions to call to handle drag-and-drop of known types.
|
||||||
If the type for the drop is not present, or the function is nil,
|
If the type of the drop is not present in the alist, or the
|
||||||
the drop is rejected. The function takes three arguments, WINDOW, ACTION
|
function corresponding to the type is nil, the drop of that
|
||||||
and DATA. WINDOW is where the drop occurred, ACTION is the action for
|
type will be rejected.
|
||||||
this drop (copy, move, link, private or ask) as determined by a previous
|
|
||||||
call to `x-dnd-test-function'. DATA is the drop data.
|
Each function takes three arguments: WINDOW, ACTION, and DATA.
|
||||||
The function shall return the action used (copy, move, link or private)
|
WINDOW is the window where the drop occurred.
|
||||||
if drop is successful, nil if not."
|
ACTION is the action for this drop (`copy', `move', `link', `private'
|
||||||
|
or `ask'), as determined by a previous call to `x-dnd-test-function'.
|
||||||
|
DATA is the drop data.
|
||||||
|
The function shall return the action it used (one of the above,
|
||||||
|
excluding `ask') if drop is successful, nil if not."
|
||||||
:version "22.1"
|
:version "22.1"
|
||||||
:type 'alist
|
:type 'alist
|
||||||
:group 'x)
|
:group 'x)
|
||||||
|
@ -122,22 +126,27 @@ like xterm) for text."
|
||||||
:group 'x)
|
:group 'x)
|
||||||
|
|
||||||
(defcustom x-dnd-direct-save-function #'x-dnd-save-direct
|
(defcustom x-dnd-direct-save-function #'x-dnd-save-direct
|
||||||
"Function called when a file is dropped that Emacs must save.
|
"Function called when a file is dropped via XDS protocol.
|
||||||
It is called with two arguments: the first is either nil or t,
|
The value should be a function of two arguments that supports
|
||||||
and the second is a string.
|
the X Direct Save (XDS) protocol. The function will be called
|
||||||
|
twice during the protocol execution.
|
||||||
|
|
||||||
If the first argument is t, the second argument is the name the
|
When the function is called with the first argument non-nil,
|
||||||
dropped file should be saved under. The function should return a
|
it should return an absolute file name whose base name is
|
||||||
complete file name describing where the file should be saved.
|
the value of the second argument, a string. The return value
|
||||||
|
is the file name for the dragged file to be saved. The function
|
||||||
|
can also return nil if saving the file should be refused for some
|
||||||
|
reason; in that case the drop will be canceled.
|
||||||
|
|
||||||
It can also return nil, which means to cancel the drop.
|
When the function is called with the first argument nil, the
|
||||||
|
second argument specifies the file name where the file was saved;
|
||||||
If the first argument is nil, the second is the name of the file
|
the function should then do whatever is appropriate when such a
|
||||||
that was dropped."
|
file is saved, like show the file in the Dired buffer or visit
|
||||||
|
the file."
|
||||||
:version "29.1"
|
:version "29.1"
|
||||||
:type '(choice (const :tag "Prompt for name before saving"
|
:type '(choice (const :tag "Prompt for file name to save"
|
||||||
x-dnd-save-direct)
|
x-dnd-save-direct)
|
||||||
(const :tag "Save and open immediately without prompting"
|
(const :tag "Save in `default-directory' without prompting"
|
||||||
x-dnd-save-direct-immediately)
|
x-dnd-save-direct-immediately)
|
||||||
(function :tag "Other function"))
|
(function :tag "Other function"))
|
||||||
:group 'x)
|
:group 'x)
|
||||||
|
@ -222,14 +231,14 @@ any protocol specific data.")
|
||||||
(cdr (x-dnd-get-state-cons-for-frame frame-or-window)))
|
(cdr (x-dnd-get-state-cons-for-frame frame-or-window)))
|
||||||
|
|
||||||
(defun x-dnd-default-test-function (_window _action types)
|
(defun x-dnd-default-test-function (_window _action types)
|
||||||
"The default test function for drag and drop.
|
"The default test function for drag-and-drop.
|
||||||
WINDOW is where the mouse is when this function is called. It
|
WINDOW is where the mouse is when this function is called. It
|
||||||
may be a frame if the mouse is over the menu bar, scroll bar or
|
may be a frame if the mouse is over the menu bar, scroll bar or
|
||||||
tool bar. ACTION is the suggested action from the source, and
|
tool bar. ACTION is the suggested action from the source, and
|
||||||
TYPES are the types the drop data can have. This function only
|
TYPES are the types the drop data can have. This function only
|
||||||
accepts drops with types in `x-dnd-known-types'. It always
|
accepts drops with types in `x-dnd-known-types'. It always
|
||||||
returns the action `private', unless `types' contains a value
|
returns the action `private', unless `types' contains a value
|
||||||
inside `x-dnd-copy-types'."
|
inside `x-dnd-copy-types', in which case it may return `copy'."
|
||||||
(let ((type (x-dnd-choose-type types)))
|
(let ((type (x-dnd-choose-type types)))
|
||||||
(when type (let ((list x-dnd-copy-types))
|
(when type (let ((list x-dnd-copy-types))
|
||||||
(catch 'out
|
(catch 'out
|
||||||
|
@ -1564,17 +1573,24 @@ was taken, or the direct save failed."
|
||||||
(when (not (equal file-name original-file-name))
|
(when (not (equal file-name original-file-name))
|
||||||
(delete-file file-name)))))
|
(delete-file file-name)))))
|
||||||
|
|
||||||
(defun x-dnd-save-direct (need-name name)
|
(defun x-dnd-save-direct (need-name filename)
|
||||||
"Handle dropping a file that should be saved immediately.
|
"Handle dropping a file FILENAME that should be saved first, asking the user.
|
||||||
NEED-NAME tells whether or not the file was not yet saved. NAME
|
NEED-NAME non-nil means the caller requests the full absolute
|
||||||
is either the name of the file, or the name the drop source wants
|
file name of FILENAME under which to save it; FILENAME is just
|
||||||
us to save under.
|
the base name in that case. The function then prompts the user
|
||||||
|
for where to save to file and returns the result to the caller.
|
||||||
|
|
||||||
Prompt the user for a file name, then open it."
|
NEED-NAME nil means the file was saved as FILENAME (which should
|
||||||
|
be the full absolute file name in that case). The function then
|
||||||
|
refreshes the Dired display, if the current buffer is in Dired
|
||||||
|
mode, or visits the file otherwise.
|
||||||
|
|
||||||
|
This function is intended to be the value of `x-dnd-direct-save-function',
|
||||||
|
which see."
|
||||||
(if need-name
|
(if need-name
|
||||||
(let ((file-name (read-file-name "Write file: "
|
(let ((file-name (read-file-name "Write file: "
|
||||||
default-directory
|
default-directory
|
||||||
nil nil name)))
|
nil nil filename)))
|
||||||
(when (file-exists-p file-name)
|
(when (file-exists-p file-name)
|
||||||
(unless (y-or-n-p (format-message
|
(unless (y-or-n-p (format-message
|
||||||
"File `%s' exists; overwrite? " file-name))
|
"File `%s' exists; overwrite? " file-name))
|
||||||
|
@ -1584,18 +1600,18 @@ Prompt the user for a file name, then open it."
|
||||||
;; interface can be found.
|
;; interface can be found.
|
||||||
(if (derived-mode-p 'dired-mode)
|
(if (derived-mode-p 'dired-mode)
|
||||||
(revert-buffer)
|
(revert-buffer)
|
||||||
(find-file name))))
|
(find-file filename))))
|
||||||
|
|
||||||
(defun x-dnd-save-direct-immediately (need-name name)
|
(defun x-dnd-save-direct-immediately (need-name filename)
|
||||||
"Save and open a dropped file, like `x-dnd-save-direct'.
|
"Handle dropping a file FILENAME that should be saved first.
|
||||||
NEED-NAME tells whether or not the file was not yet saved. NAME
|
Like `x-dnd-save-direct', but do not prompt for the file name;
|
||||||
is either the name of the file, or the name the drop source wants
|
instead, return its absolute file name for saving in the current
|
||||||
us to save under.
|
directory.
|
||||||
|
|
||||||
Unlike `x-dnd-save-direct', do not prompt for the name by which
|
This function is intended to be the value of `x-dnd-direct-save-function',
|
||||||
to save the file. Simply save it in the current directory."
|
which see."
|
||||||
(if need-name
|
(if need-name
|
||||||
(let ((file-name (expand-file-name name)))
|
(let ((file-name (expand-file-name filename)))
|
||||||
(when (file-exists-p file-name)
|
(when (file-exists-p file-name)
|
||||||
(unless (y-or-n-p (format-message
|
(unless (y-or-n-p (format-message
|
||||||
"File `%s' exists; overwrite? " file-name))
|
"File `%s' exists; overwrite? " file-name))
|
||||||
|
@ -1605,7 +1621,7 @@ to save the file. Simply save it in the current directory."
|
||||||
;; interface can be found.
|
;; interface can be found.
|
||||||
(if (derived-mode-p 'dired-mode)
|
(if (derived-mode-p 'dired-mode)
|
||||||
(revert-buffer)
|
(revert-buffer)
|
||||||
(find-file name))))
|
(find-file filename))))
|
||||||
|
|
||||||
(defun x-dnd-handle-octet-stream-for-drop (save-to)
|
(defun x-dnd-handle-octet-stream-for-drop (save-to)
|
||||||
"Save the contents of the XDS selection to SAVE-TO.
|
"Save the contents of the XDS selection to SAVE-TO.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue