emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 2ce686c049 2/2: Support dragging multiple files on NS


From: Po Lu
Subject: master 2ce686c049 2/2: Support dragging multiple files on NS
Date: Sat, 4 Jun 2022 03:47:38 -0400 (EDT)

branch: master
commit 2ce686c049a7a35cdc3eb87626d8a94539388a35
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Support dragging multiple files on NS
    
    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 | 20 +++++++++++++++-----
 src/nsselect.m      | 50 ++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 57 insertions(+), 13 deletions(-)

diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el
index a36d5d11e7..2e021b9b29 100644
--- a/lisp/term/ns-win.el
+++ b/lisp/term/ns-win.el
@@ -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)
diff --git a/src/nsselect.m b/src/nsselect.m
index a4129b12f0..a719eef4e8 100644
--- a/src/nsselect.m
+++ b/src/nsselect.m
@@ -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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]