aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2023-04-08 18:36:23 +0300
committerEli Zaretskii2023-04-08 18:36:23 +0300
commit08cda286c3f5ccf4a898516204884bd7daaae971 (patch)
treea75ae38b7750a6e4d69cbc362e27b9a9e12da84e
parent14d1c00e806cbd864acc6b4a6f84a4453954b898 (diff)
downloademacs-08cda286c3f5ccf4a898516204884bd7daaae971.tar.gz
emacs-08cda286c3f5ccf4a898516204884bd7daaae971.zip
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.
-rw-r--r--doc/lispref/frames.texi88
-rw-r--r--lisp/x-dnd.el120
2 files changed, 133 insertions, 75 deletions
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 7cae94d2627..c78ab1c34ba 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -4112,7 +4112,7 @@ has the same meaning as the @var{action} argument to
4112 Emacs implements receiving text and URLs individually for each 4112 Emacs implements receiving text and URLs individually for each
4113window system, and does not by default support receiving other kinds 4113window system, and does not by default support receiving other kinds
4114of data as drops. To support receiving other kinds of data, use the 4114of data as drops. To support receiving other kinds of data, use the
4115X-specific interface described below: 4115X-specific interface described below.
4116 4116
4117@vindex x-dnd-test-function 4117@vindex x-dnd-test-function
4118@vindex x-dnd-known-types 4118@vindex x-dnd-known-types
@@ -4141,29 +4141,71 @@ depending on the specific drag-and-drop protocol being used. For
4141example, the data type used for plain text may be either 4141example, the data type used for plain text may be either
4142@code{"STRING"} or @code{"text/plain"}. 4142@code{"STRING"} or @code{"text/plain"}.
4143 4143
4144@cindex XDS
4145@cindex direct save protocol
4144@vindex x-dnd-direct-save-function 4146@vindex x-dnd-direct-save-function
4145@c FIXME: This description is overly-complicated and confusing. In 4147 When Emacs runs on X window system, it supports the X Direct Save
4146@c particular, the two calls to the function basically sound 4148(@acronym{XDS}) protocol, which allows users to save a file by
4147@c identical, so it is unclear how should the function distinguish 4149dragging and dropping it onto an Emacs window, such as a Dired window.
4148@c between the first and the second one. The description of who asks 4150To comply with the unique requirements of @acronym{XDS}, these
4149@c whom to do what is also very hard to understand. Needs rewording, 4151drag-and-drop requests are processed specially: instead of being
4150@c and needs shorter sentences. Perhaps examples could help. 4152handled according to @code{x-dnd-types-alist}, they are handled by the
4151 However, @code{x-dnd-types-alist} does not handle a special kind of 4153@dfn{direct-save function} that is the value of the variable
4152drop sent by a program that wants Emacs to tell it where to save a 4154@code{x-dnd-direct-save-function}. The value should be a function of
4153file in a specific location determined by the user. These drops are 4155two arguments, @var{need-name} and @var{filename}. The @acronym{XDS}
4154instead handled by a function that is the value of the variable 4156protocol uses a two-step procedure for dragging files:
4155@code{x-dnd-direct-save-function}. This function should accept two arguments. 4157
4156If the first argument is non-@code{nil}, then the second argument is a 4158@enumerate 1
4157file name to save (with leading directories) that the other 4159@item
4158program recommends, and the 4160The application from which the file is dragged asks Emacs to provide
4159function should return the full file name under which it should be 4161the full file name under which to save the file. For this purpose,
4160saved. After the function completes, Emacs will ask the other program 4162the direct-save function is called with its first argument
4161to save the file under the name that was returned, and if the file was 4163@var{need-name} non-@code{nil}, and the second argument @var{filename}
4162successfully saved, call the function again with the first argument 4164set to the basename of the file to be saved. It should return the
4163set to a non-@code{nil} value and the second argument set to the file 4165fully-expanded absolute file name under which to save the file. For
4164name that was returned. The function should then perform whatever 4166example, if a file is dragged to a Dired window, the natural directory
4165action is appropriate (i.e., opening the file or refreshing a 4167for the file is the directory of the file shown at location of the
4166directory listing.) 4168drop. If saving the file is not possible for some reason, the
4169function should return @code{nil}, which will cancel the drag-and-drop
4170operation.
4171
4172@item
4173The application from which the file is dragged saves the file under
4174the name returned by the first call to the direct-save function. If
4175it succeeds in saving the file, the direct-save function is called
4176again, this time with the first argument @var{need-name} set to
4177@code{nil} and the second argument @var{filename} set to the full
4178absolute name of the saved file. The function is then expected to do
4179whatever is needed given the fact that file was saved. For example,
4180Dired should update the directory on display by showing the new file
4181there.
4182@end enumerate
4183
4184The default value of @code{x-dnd-direct-save-function} is
4185@code{x-dnd-save-direct}.
4186
4187@defun x-dnd-save-direct need-name filename
4188When called with the @var{need-name} argument non-@code{nil}, this
4189function prompts the user for the absolute file name under which it
4190should be saved. If the specified file already exists, it
4191additionally asks the user whether to overwrite it, and returns the
4192absolute file name only if the user confirms the overwriting.
4193
4194When called with the @var{need-name} argument @code{nil}, it reverts
4195the Dired listing if the current buffer is in Dired mode or one of its
4196descendants, and otherwise visits the file by calling @code{find-file}
4197(@pxref{Visiting Functions}).
4198@end defun
4199
4200@defun x-dnd-save-direct-immediately need-name filename
4201This function works like @code{x-dnd-save-direct}, but when called
4202with its @var{need-name} argument non-@code{nil}, it doesn't prompt
4203the user for the full name of the file to be saved; instead, it
4204returns its argument @var{filename} expanded against the current
4205buffer's default directory (@pxref{File Name Expansion}). (It still
4206asks for confirmation if a file by that name already exists in the
4207default directory.)
4208@end defun
4167 4209
4168@cindex initiating drag-and-drop 4210@cindex initiating drag-and-drop
4169 On capable window systems, Emacs also supports dragging contents 4211 On capable window systems, Emacs also supports dragging contents
diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el
index b213b155249..9286a1858cf 100644
--- a/lisp/x-dnd.el
+++ b/lisp/x-dnd.el
@@ -34,20 +34,20 @@
34 34
35;;; Customizable variables 35;;; Customizable variables
36(defcustom x-dnd-test-function #'x-dnd-default-test-function 36(defcustom x-dnd-test-function #'x-dnd-default-test-function
37 "The function drag and drop uses to determine if to accept or reject a drop. 37 "Function to be used by drag-and-drop to determine whether to accept a drop.
38The function takes three arguments, WINDOW, ACTION and TYPES. 38The function takes three arguments: WINDOW, ACTION, and TYPES.
39WINDOW is where the mouse is when the function is called. WINDOW 39WINDOW is where the window under the mouse is when the function is called.
40may be a frame if the mouse isn't over a real window (i.e. menu 40WINDOW may be a frame if the mouse isn't over a real window (e.g., menu
41bar, tool bar or scroll bar). ACTION is the suggested action 41bar, tool bar, scroll bar, etc.).
42from the drag and drop source, one of the symbols move, copy, 42ACTION is the suggested action from the drag and drop source, one of the
43link or ask. TYPES is a vector of available types for the drop. 43symbols `move', `copy', `link' or `ask'.
44 44TYPES is a vector of available types for the drop.
45Each element of TYPE should either be a string (containing the 45Each element of TYPES should either be a string (containing the
46name of the type's X atom), or a symbol, whose name will be used. 46name of the type's X atom), or a symbol, whose name will be used.
47 47
48The function shall return nil to reject the drop or a cons with 48The function shall return nil to reject the drop or a cons with
49two values, the wanted action as car and the wanted type as cdr. 49two values, the wanted action as `car' and the wanted type as `cdr'.
50The wanted action can be copy, move, link, ask or private. 50The wanted action can be `copy', `move', `link', `ask' or `private'.
51 51
52The default value for this variable is `x-dnd-default-test-function'." 52The default value for this variable is `x-dnd-default-test-function'."
53 :version "22.1" 53 :version "22.1"
@@ -70,14 +70,18 @@ The default value for this variable is `x-dnd-default-test-function'."
70 (,(purecopy "DndTypeFile") . x-dnd-handle-offix-file) 70 (,(purecopy "DndTypeFile") . x-dnd-handle-offix-file)
71 (,(purecopy "DndTypeFiles") . x-dnd-handle-offix-files) 71 (,(purecopy "DndTypeFiles") . x-dnd-handle-offix-files)
72 (,(purecopy "DndTypeText") . dnd-insert-text)) 72 (,(purecopy "DndTypeText") . dnd-insert-text))
73 "Which function to call to handle a drop of that type. 73 "Functions to call to handle drag-and-drop of known types.
74If the type for the drop is not present, or the function is nil, 74If the type of the drop is not present in the alist, or the
75the drop is rejected. The function takes three arguments, WINDOW, ACTION 75function corresponding to the type is nil, the drop of that
76and DATA. WINDOW is where the drop occurred, ACTION is the action for 76type will be rejected.
77this drop (copy, move, link, private or ask) as determined by a previous 77
78call to `x-dnd-test-function'. DATA is the drop data. 78Each function takes three arguments: WINDOW, ACTION, and DATA.
79The function shall return the action used (copy, move, link or private) 79WINDOW is the window where the drop occurred.
80if drop is successful, nil if not." 80ACTION is the action for this drop (`copy', `move', `link', `private'
81or `ask'), as determined by a previous call to `x-dnd-test-function'.
82DATA is the drop data.
83The function shall return the action it used (one of the above,
84excluding `ask') if drop is successful, nil if not."
81 :version "22.1" 85 :version "22.1"
82 :type 'alist 86 :type 'alist
83 :group 'x) 87 :group 'x)
@@ -122,22 +126,27 @@ like xterm) for text."
122 :group 'x) 126 :group 'x)
123 127
124(defcustom x-dnd-direct-save-function #'x-dnd-save-direct 128(defcustom x-dnd-direct-save-function #'x-dnd-save-direct
125 "Function called when a file is dropped that Emacs must save. 129 "Function called when a file is dropped via XDS protocol.
126It is called with two arguments: the first is either nil or t, 130The value should be a function of two arguments that supports
127and the second is a string. 131the X Direct Save (XDS) protocol. The function will be called
128 132twice during the protocol execution.
129If the first argument is t, the second argument is the name the 133
130dropped file should be saved under. The function should return a 134When the function is called with the first argument non-nil,
131complete file name describing where the file should be saved. 135it should return an absolute file name whose base name is
132 136the value of the second argument, a string. The return value
133It can also return nil, which means to cancel the drop. 137is the file name for the dragged file to be saved. The function
134 138can also return nil if saving the file should be refused for some
135If the first argument is nil, the second is the name of the file 139reason; in that case the drop will be canceled.
136that was dropped." 140
141When the function is called with the first argument nil, the
142second argument specifies the file name where the file was saved;
143the function should then do whatever is appropriate when such a
144file is saved, like show the file in the Dired buffer or visit
145the file."
137 :version "29.1" 146 :version "29.1"
138 :type '(choice (const :tag "Prompt for name before saving" 147 :type '(choice (const :tag "Prompt for file name to save"
139 x-dnd-save-direct) 148 x-dnd-save-direct)
140 (const :tag "Save and open immediately without prompting" 149 (const :tag "Save in `default-directory' without prompting"
141 x-dnd-save-direct-immediately) 150 x-dnd-save-direct-immediately)
142 (function :tag "Other function")) 151 (function :tag "Other function"))
143 :group 'x) 152 :group 'x)
@@ -222,14 +231,14 @@ any protocol specific data.")
222 (cdr (x-dnd-get-state-cons-for-frame frame-or-window))) 231 (cdr (x-dnd-get-state-cons-for-frame frame-or-window)))
223 232
224(defun x-dnd-default-test-function (_window _action types) 233(defun x-dnd-default-test-function (_window _action types)
225 "The default test function for drag and drop. 234 "The default test function for drag-and-drop.
226WINDOW is where the mouse is when this function is called. It 235WINDOW is where the mouse is when this function is called. It
227may be a frame if the mouse is over the menu bar, scroll bar or 236may be a frame if the mouse is over the menu bar, scroll bar or
228tool bar. ACTION is the suggested action from the source, and 237tool bar. ACTION is the suggested action from the source, and
229TYPES are the types the drop data can have. This function only 238TYPES are the types the drop data can have. This function only
230accepts drops with types in `x-dnd-known-types'. It always 239accepts drops with types in `x-dnd-known-types'. It always
231returns the action `private', unless `types' contains a value 240returns the action `private', unless `types' contains a value
232inside `x-dnd-copy-types'." 241inside `x-dnd-copy-types', in which case it may return `copy'."
233 (let ((type (x-dnd-choose-type types))) 242 (let ((type (x-dnd-choose-type types)))
234 (when type (let ((list x-dnd-copy-types)) 243 (when type (let ((list x-dnd-copy-types))
235 (catch 'out 244 (catch 'out
@@ -1564,17 +1573,24 @@ was taken, or the direct save failed."
1564 (when (not (equal file-name original-file-name)) 1573 (when (not (equal file-name original-file-name))
1565 (delete-file file-name))))) 1574 (delete-file file-name)))))
1566 1575
1567(defun x-dnd-save-direct (need-name name) 1576(defun x-dnd-save-direct (need-name filename)
1568 "Handle dropping a file that should be saved immediately. 1577 "Handle dropping a file FILENAME that should be saved first, asking the user.
1569NEED-NAME tells whether or not the file was not yet saved. NAME 1578NEED-NAME non-nil means the caller requests the full absolute
1570is either the name of the file, or the name the drop source wants 1579file name of FILENAME under which to save it; FILENAME is just
1571us to save under. 1580the base name in that case. The function then prompts the user
1581for where to save to file and returns the result to the caller.
1582
1583NEED-NAME nil means the file was saved as FILENAME (which should
1584be the full absolute file name in that case). The function then
1585refreshes the Dired display, if the current buffer is in Dired
1586mode, or visits the file otherwise.
1572 1587
1573Prompt the user for a file name, then open it." 1588This function is intended to be the value of `x-dnd-direct-save-function',
1589which see."
1574 (if need-name 1590 (if need-name
1575 (let ((file-name (read-file-name "Write file: " 1591 (let ((file-name (read-file-name "Write file: "
1576 default-directory 1592 default-directory
1577 nil nil name))) 1593 nil nil filename)))
1578 (when (file-exists-p file-name) 1594 (when (file-exists-p file-name)
1579 (unless (y-or-n-p (format-message 1595 (unless (y-or-n-p (format-message
1580 "File `%s' exists; overwrite? " file-name)) 1596 "File `%s' exists; overwrite? " file-name))
@@ -1584,18 +1600,18 @@ Prompt the user for a file name, then open it."
1584 ;; interface can be found. 1600 ;; interface can be found.
1585 (if (derived-mode-p 'dired-mode) 1601 (if (derived-mode-p 'dired-mode)
1586 (revert-buffer) 1602 (revert-buffer)
1587 (find-file name)))) 1603 (find-file filename))))
1588 1604
1589(defun x-dnd-save-direct-immediately (need-name name) 1605(defun x-dnd-save-direct-immediately (need-name filename)
1590 "Save and open a dropped file, like `x-dnd-save-direct'. 1606 "Handle dropping a file FILENAME that should be saved first.
1591NEED-NAME tells whether or not the file was not yet saved. NAME 1607Like `x-dnd-save-direct', but do not prompt for the file name;
1592is either the name of the file, or the name the drop source wants 1608instead, return its absolute file name for saving in the current
1593us to save under. 1609directory.
1594 1610
1595Unlike `x-dnd-save-direct', do not prompt for the name by which 1611This function is intended to be the value of `x-dnd-direct-save-function',
1596to save the file. Simply save it in the current directory." 1612which see."
1597 (if need-name 1613 (if need-name
1598 (let ((file-name (expand-file-name name))) 1614 (let ((file-name (expand-file-name filename)))
1599 (when (file-exists-p file-name) 1615 (when (file-exists-p file-name)
1600 (unless (y-or-n-p (format-message 1616 (unless (y-or-n-p (format-message
1601 "File `%s' exists; overwrite? " file-name)) 1617 "File `%s' exists; overwrite? " file-name))
@@ -1605,7 +1621,7 @@ to save the file. Simply save it in the current directory."
1605 ;; interface can be found. 1621 ;; interface can be found.
1606 (if (derived-mode-p 'dired-mode) 1622 (if (derived-mode-p 'dired-mode)
1607 (revert-buffer) 1623 (revert-buffer)
1608 (find-file name)))) 1624 (find-file filename))))
1609 1625
1610(defun x-dnd-handle-octet-stream-for-drop (save-to) 1626(defun x-dnd-handle-octet-stream-for-drop (save-to)
1611 "Save the contents of the XDS selection to SAVE-TO. 1627 "Save the contents of the XDS selection to SAVE-TO.