From: Po Lu Date: Wed, 1 Jun 2022 05:50:40 +0000 (+0800) Subject: Implement `allow-same-frame' for NS drag-and-drop X-Git-Tag: emacs-29.0.90~1910^2~295^2~26 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=76850b26b92ab0f23d56180d000063d4ad6e08ca;p=emacs.git Implement `allow-same-frame' for NS drag-and-drop * 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. --- diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index 65abdcf0fbf..a36d5d11e79 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -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. diff --git a/src/nsselect.m b/src/nsselect.m index 63cea365e23..a4129b12f03 100644 --- a/src/nsselect.m +++ b/src/nsselect.m @@ -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) { diff --git a/src/nsterm.h b/src/nsterm.h index c39b66534f6..37bff6260a0 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -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 diff --git a/src/nsterm.m b/src/nsterm.m index f4fde9bd127..46ce2cc5e44 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -8608,13 +8608,30 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action) -(NSDragOperation) draggingEntered: (id ) 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 ) sender +-(BOOL) prepareForDragOperation: (id ) 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 ) sender +- (BOOL) performDragOperation: (id ) 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];