]> git.eshelyaron.com Git - emacs.git/commitdiff
Support dragging multiple files on NS
authorPo Lu <luangruo@yahoo.com>
Sat, 4 Jun 2022 07:45:41 +0000 (15:45 +0800)
committerPo Lu <luangruo@yahoo.com>
Sat, 4 Jun 2022 07:45:41 +0000 (15:45 +0800)
This has to use a deprecated pasteboard type, since Emacs uses
the "old" (but not deprecated) dragImage: method for
drag-and-drop, which can't drop file URLs.

* lisp/term/ns-win.el (x-begin-drag): Update accordingly.
* src/nsselect.m (ns_decode_data_to_pasteboard):
(Fns_begin_drag): Allow files to be a list of filenames as well.

lisp/term/ns-win.el
src/nsselect.m

index a36d5d11e79458a3db7c03ac33e3f0f1f14233a5..2e021b9b29c13752dac84498cf5883d47b864a41 100644 (file)
@@ -905,11 +905,21 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
       (push (cons 'string ns-dnd-selection-value) pasteboard))
     (when (and (member "FILE_NAME" targets)
                (file-exists-p ns-dnd-selection-value))
-      (push (cons 'file
-                  (url-encode-url (concat "file://"
-                                          (expand-file-name
-                                           ns-dnd-selection-value))))
-            pasteboard))
+      (let ((value (if (stringp ns-dnd-selection-value)
+                       (or (get-text-property 0 'FILE_NAME
+                                              ns-dnd-selection-value)
+                           ns-dnd-selection-value)
+                     ns-dnd-selection-value)))
+        (if (vectorp value)
+            (push (cons 'file
+                        (cl-loop for file across value
+                                 collect (expand-file-name file)))
+                  pasteboard)
+          (push (cons 'file
+                      (url-encode-url (concat "file://"
+                                              (expand-file-name
+                                               ns-dnd-selection-value))))
+                pasteboard))))
     (ns-begin-drag frame pasteboard action return-frame allow-current-frame)))
 
 (defun ns-handle-drag-motion (frame x y)
index a4129b12f039c013f3268edb80eed7d886a10e36..a719eef4e860510e7e01b4b6ec18473642214f34 100644 (file)
@@ -562,8 +562,12 @@ ns_decode_data_to_pasteboard (Lisp_Object type, Lisp_Object data,
                              NSPasteboard *pasteboard)
 {
   NSArray *types, *new;
+  NSMutableArray *temp;
+  Lisp_Object tem;
+  specpdl_ref count;
 
   types = [pasteboard types];
+  count = SPECPDL_INDEX ();
 
   CHECK_SYMBOL (type);
 
@@ -580,10 +584,11 @@ ns_decode_data_to_pasteboard (Lisp_Object type, Lisp_Object data,
     }
   else if (EQ (type, Qfile))
     {
-      CHECK_STRING (data);
-
 #if NS_USE_NSPasteboardTypeFileURL
-      new = [types arrayByAddingObject: NSPasteboardTypeFileURL];
+      if (CONSP (data))
+       new = [types arrayByAddingObject: NSPasteboardTypeURL];
+      else
+       new = [types arrayByAddingObject: NSPasteboardTypeFileURL];
 #else
       new = [types arrayByAddingObject: NSFilenamesPboardType];
 #endif
@@ -591,13 +596,41 @@ ns_decode_data_to_pasteboard (Lisp_Object type, Lisp_Object data,
       [pasteboard declareTypes: new
                         owner: nil];
 
+      if (STRINGP (data))
+       {
 #if NS_USE_NSPasteboardTypeFileURL
-      [pasteboard setString: [NSString stringWithLispString: data]
-                   forType: NSPasteboardTypeFileURL];
+         [pasteboard setString: [NSString stringWithLispString: data]
+                       forType: NSPasteboardTypeFileURL];
 #else
-      [pasteboard setString: [NSString stringWithLispString: data]
-                   forType: NSFilenamesPboardType];
+         [pasteboard setString: [NSString stringWithLispString: data]
+                       forType: NSFilenamesPboardType];
+#endif
+       }
+      else
+       {
+         CHECK_LIST (data);
+         temp = [[NSMutableArray alloc] init];
+         record_unwind_protect_ptr (ns_release_object, temp);
+
+         for (tem = data; CONSP (tem); tem = XCDR (tem))
+           {
+             CHECK_STRING (XCAR (tem));
+
+             [temp addObject: [NSString stringWithLispString: XCAR (tem)]];
+           }
+         CHECK_LIST_END (tem, data);
+#if NS_USE_NSPasteboardTypeFileURL
+         [pasteboard setPropertyList: temp
+                     /* We have to use this deprecated pasteboard
+                        type, since Apple doesn't let us use
+                        dragImage:at: to drag multiple file URLs.  */
+                             forType: @"NSFilenamesPboardType"];
+#else
+         [pasteboard setPropertyList: temp
+                             forType: NSFilenamesPboardType];
 #endif
+         unbind_to (count, Qnil);
+       }
     }
   else
     signal_error ("Unknown pasteboard type", type);
@@ -673,7 +706,8 @@ the meaning of DATA:
     be dragged to another program.
 
   - `file' means DATA should be a file URL that will be dragged to
-    another program.
+    another program.  DATA may also be a list of file names; that
+    means each file in the list will be dragged to another program.
 
 ACTION is the action that will be taken by the drop target towards the
 data inside PBOARD.