]> git.eshelyaron.com Git - emacs.git/commitdiff
Implement `allow-same-frame' for NS drag-and-drop
authorPo Lu <luangruo@yahoo.com>
Wed, 1 Jun 2022 05:50:40 +0000 (13:50 +0800)
committerPo Lu <luangruo@yahoo.com>
Wed, 1 Jun 2022 05:50:40 +0000 (13:50 +0800)
* lisp/term/ns-win.el (x-begin-drag): Implement
`allow-same-frame'.
* src/nsselect.m (Fns_begin_drag): New parameter
`allow-same-frame'.
* src/nsterm.h (@interface EmacsWindow): Update prototypes.
* src/nsterm.m ([EmacsView draggingEntered:]):
([EmacsView prepareForDragOperation:]):
([EmacsView performDragOperation:]): Respect new parameter.
([EmacsWindow beginDrag:forPasteboard:withMode:returnFrameTo:]):
Likewise.

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

index 65abdcf0fbfec8d2d7d88d8918a9daecfc79d5c9..a36d5d11e79458a3db7c03ac33e3f0f1f14233a5 100644 (file)
@@ -895,7 +895,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
                                          &context (window-system ns))
   (ns-get-selection selection-symbol target-type))
 
-(defun x-begin-drag (targets &optional action frame return-frame _allow-current-frame)
+(defun x-begin-drag (targets &optional action frame return-frame allow-current-frame)
   "SKIP: real doc in xfns.c."
   (unless ns-dnd-selection-value
     (error "No local value for XdndSelection"))
@@ -910,7 +910,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
                                           (expand-file-name
                                            ns-dnd-selection-value))))
             pasteboard))
-    (ns-begin-drag frame pasteboard action return-frame)))
+    (ns-begin-drag frame pasteboard action return-frame allow-current-frame)))
 
 (defun ns-handle-drag-motion (frame x y)
   "Handle mouse movement on FRAME at X and Y during drag-and-drop.
index 63cea365e233916ca164b4e479173da6ab0d070a..a4129b12f039c013f3268edb80eed7d886a10e36 100644 (file)
@@ -662,7 +662,7 @@ ns_dnd_action_from_operation (NSDragOperation operation)
     }
 }
 
-DEFUN ("ns-begin-drag", Fns_begin_drag, Sns_begin_drag, 3, 4, 0,
+DEFUN ("ns-begin-drag", Fns_begin_drag, Sns_begin_drag, 3, 5, 0,
        doc: /* Begin a drag-and-drop operation on FRAME.
 
 FRAME must be a window system frame.  PBOARD is an alist of (TYPE
@@ -680,13 +680,16 @@ data inside PBOARD.
 
 Return the action that the drop target actually chose to perform, or
 nil if no action was performed (either because there was no drop
-target, or the drop was rejected).  If RETURN_FRAME is the symbol
+target, or the drop was rejected).  If RETURN-FRAME is the symbol
 `now', also return any frame that mouse moves into during the
 drag-and-drop operation, whilst simultaneously cancelling it.  Any
 other non-nil value means to do the same, but to wait for the mouse to
-leave FRAME first.  */)
+leave FRAME first.
+
+If ALLOW-SAME-FRAME is nil, dropping on FRAME will result in the drop
+being ignored.  */)
   (Lisp_Object frame, Lisp_Object pboard, Lisp_Object action,
-   Lisp_Object return_frame)
+   Lisp_Object return_frame, Lisp_Object allow_same_frame)
 {
   struct frame *f, *return_to;
   NSPasteboard *pasteboard;
@@ -715,7 +718,8 @@ leave FRAME first.  */)
   operation = [window beginDrag: operation
                  forPasteboard: pasteboard
                       withMode: mode
-                 returnFrameTo: &return_to];
+                 returnFrameTo: &return_to
+                  prohibitSame: (BOOL) NILP (allow_same_frame)];
 
   if (return_to)
     {
index c39b66534f628f6cb998a52fb97343b7c86f600f..37bff6260a0519233ad38db9f5ad4cf39487770c 100644 (file)
@@ -425,6 +425,7 @@ enum ns_return_frame_mode
 
   struct frame *dnd_return_frame;
   enum ns_return_frame_mode dnd_mode;
+  BOOL dnd_allow_same_frame;
 }
 
 #ifdef NS_IMPL_GNUSTEP
@@ -444,7 +445,9 @@ enum ns_return_frame_mode
 - (NSDragOperation) beginDrag: (NSDragOperation) op
                forPasteboard: (NSPasteboard *) pasteboard
                     withMode: (enum ns_return_frame_mode) mode
-               returnFrameTo: (struct frame **) frame_return;
+               returnFrameTo: (struct frame **) frame_return
+           prohibitSame: (BOOL) prohibit_same_frame;
+- (BOOL) mustNotDropOn: (NSView *) receiver;
 @end
 
 
index f4fde9bd127a61518210bf7a68b58397244007ba..46ce2cc5e44ed17a5ebd33c249216429f054859a 100644 (file)
@@ -8608,13 +8608,30 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
 
 -(NSDragOperation) draggingEntered: (id <NSDraggingInfo>) sender
 {
+  id source;
+
   NSTRACE ("[EmacsView draggingEntered:]");
+
+  source = [sender draggingSource];
+
+  if (source && [source respondsToSelector: @selector(mustNotDropOn:)]
+      && [source mustNotDropOn: self])
+    return NSDragOperationNone;
+
   return NSDragOperationGeneric;
 }
 
 
--(BOOL)prepareForDragOperation: (id <NSDraggingInfo>) sender
+-(BOOL) prepareForDragOperation: (id <NSDraggingInfo>) sender
 {
+  id source;
+
+  source = [sender draggingSource];
+
+  if (source && [source respondsToSelector: @selector(mustNotDropOn:)]
+      && [source mustNotDropOn: self])
+    return NO;
+
   return YES;
 }
 
@@ -8675,25 +8692,29 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
   return NSDragOperationGeneric;
 }
 
--(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
+- (BOOL) performDragOperation: (id <NSDraggingInfo>) sender
 {
-  id pb;
+  id pb, source;
   int x, y;
   NSString *type;
-  NSEvent *theEvent = [[self window] currentEvent];
   NSPoint position;
   NSDragOperation op = [sender draggingSourceOperationMask];
   Lisp_Object operations = Qnil;
   Lisp_Object strings = Qnil;
   Lisp_Object type_sym;
+  struct input_event ie;
 
   NSTRACE ("[EmacsView performDragOperation:]");
 
-  if (!emacs_event)
+  source = [sender draggingSource];
+
+  if (source && [source respondsToSelector: @selector(mustNotDropOn:)]
+      && [source mustNotDropOn: self])
     return NO;
 
   position = [self convertPoint: [sender draggingLocation] fromView: nil];
-  x = lrint (position.x);  y = lrint (position.y);
+  x = lrint (position.x);
+  y = lrint (position.y);
 
   pb = [sender draggingPasteboard];
   type = [pb availableTypeFromArray: ns_drag_types];
@@ -8709,10 +8730,8 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
   if (op & NSDragOperationGeneric || NILP (operations))
     operations = Fcons (Qns_drag_operation_generic, operations);
 
-  if (type == 0)
-    {
-      return NO;
-    }
+  if (!type)
+    return NO;
 #if NS_USE_NSPasteboardTypeFileURL != 0
   else if ([type isEqualToString: NSPasteboardTypeFileURL])
     {
@@ -8764,21 +8783,16 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
       strings = list1 ([data lispString]);
     }
   else
-    {
-      fputs ("Invalid data type in dragging pasteboard\n", stderr);
-      return NO;
-    }
-
-  emacs_event->kind = DRAG_N_DROP_EVENT;
-  XSETINT (emacs_event->x, x);
-  XSETINT (emacs_event->y, y);
-  emacs_event->modifiers = 0;
+    return NO;
 
-  emacs_event->arg = Fcons (type_sym,
-                            Fcons (operations,
-                                   strings));
-  EV_TRAILER (theEvent);
+  EVENT_INIT (ie);
+  ie.kind = DRAG_N_DROP_EVENT;
+  ie.arg = Fcons (type_sym, Fcons (operations, strings));
+  XSETINT (ie.x, x);
+  XSETINT (ie.y, y);
+  XSETFRAME (ie.frame_or_window, emacsframe);
 
+  kbd_buffer_store_event (&ie);
   return YES;
 }
 
@@ -9611,10 +9625,17 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
 }
 #endif
 
+- (BOOL) mustNotDropOn: (NSView *) receiver
+{
+  return ([receiver window] == self
+         ? !dnd_allow_same_frame : NO);
+}
+
 - (NSDragOperation) beginDrag: (NSDragOperation) op
                forPasteboard: (NSPasteboard *) pasteboard
                     withMode: (enum ns_return_frame_mode) mode
                returnFrameTo: (struct frame **) frame_return
+                prohibitSame: (BOOL) prohibit_same_frame
 {
   NSImage *image;
 #ifdef NS_IMPL_COCOA
@@ -9627,6 +9648,7 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
   image = [[NSImage alloc] initWithSize: NSMakeSize (1.0, 1.0)];
   dnd_mode = mode;
   dnd_return_frame = NULL;
+  dnd_allow_same_frame = !prohibit_same_frame;
 
   /* Now draw transparency onto the image.  */
   [image lockFocus];