Commit c342b263 authored by Alan Third's avatar Alan Third
Browse files

Fix drag and drop behaviour on NS (bug#30929)

* doc/emacs/macos.texi (Mac / GNUstep Events): Describe the new drag
and drop behaviour.
* lisp/term/ns-win.el (ns-drag-n-drop): Handle the new event format.
(ns-drag-n-drop-other-frame):
(ns-drag-n-drop-as-text):
(ns-drag-n-drop-as-text-other-frame): Remove functions and key
bindings.
* src/nsterm.m ([EmacsView performDragOperation:]): Send Emacs event
in new format without setting any modifiers.
parent 7ae0a24c
...@@ -170,8 +170,25 @@ the requested line (@code{ns-open-file-select-line}). ...@@ -170,8 +170,25 @@ the requested line (@code{ns-open-file-select-line}).
This event occurs when a user drags an object from another application This event occurs when a user drags an object from another application
into an Emacs frame. The default behavior is to open a file in the into an Emacs frame. The default behavior is to open a file in the
window under the mouse, or to insert text at point of the window under window under the mouse, or to insert text at point of the window under
the mouse. It may sometimes be necessary to use the @key{Meta} key in the mouse.
conjunction with dragging to force text insertion.
The sending application has some limited ability to decide how Emacs
handles the sent object, but the user may override the default
behaviour by holding one or more modifier key.
@table @kbd
@item control
Insert as text in the current buffer. If the object is a file, this
will insert the filename.
@item alt/option
Attempt to open the object as though it is a file or URL.
@item super/command
Perform the default action for the type. This can be useful when an
application is overriding the default behaviour.
@end table
The modifier keys listed above are defined by macOS and are unaffected
by user changes to the modifiers in Emacs.
@item ns-change-font @item ns-change-font
This event occurs when the user selects a font in a Nextstep font This event occurs when the user selects a font in a Nextstep font
......
...@@ -1494,6 +1494,12 @@ versions of MS-Windows. Set this variable to 50 if for some reason ...@@ -1494,6 +1494,12 @@ versions of MS-Windows. Set this variable to 50 if for some reason
you need the old behavior (and please report such situations to Emacs you need the old behavior (and please report such situations to Emacs
developers). developers).
+++
** On NS the behaviour of drag and drop can now be modified by use of
modifier keys in line with Apples guidelines. This makes the drag and
drop behaviour more consistent, as previously the sending application
was able to 'set' modifiers without the knowledge of the user.
---------------------------------------------------------------------- ----------------------------------------------------------------------
This file is part of GNU Emacs. This file is part of GNU Emacs.
......
...@@ -501,48 +501,38 @@ unless the current buffer is a scratch buffer." ...@@ -501,48 +501,38 @@ unless the current buffer is a scratch buffer."
(find-file f))))) (find-file f)))))
(defun ns-drag-n-drop (event &optional new-frame force-text) (defun ns-drag-n-drop (event)
"Edit the files listed in the drag-n-drop EVENT. "Edit the files listed in the drag-n-drop EVENT.
Switch to a buffer editing the last file dropped." Switch to a buffer editing the last file dropped, or insert the
string dropped into the current buffer."
(interactive "e") (interactive "e")
(let* ((window (posn-window (event-start event))) (let* ((window (posn-window (event-start event)))
(arg (car (cdr (cdr event)))) (arg (car (cdr (cdr event))))
(type (car arg)) (type (car arg))
(data (car (cdr arg))) (operations (car (cdr arg)))
(url-or-string (cond ((eq type 'file) (objects (cdr (cdr arg)))
(concat "file:" data)) (string (mapconcat 'identity objects "\n")))
(t data))))
(set-frame-selected-window nil window) (set-frame-selected-window nil window)
(when new-frame
(select-frame (make-frame)))
(raise-frame) (raise-frame)
(setq window (selected-window)) (setq window (selected-window))
(if force-text (cond ((memq 'ns-drag-operation-generic operations)
(dnd-insert-text window 'private data) ;; Perform the default action for the type.
(dnd-handle-one-url window 'private url-or-string)))) (if (eq type 'file)
(dolist (data objects)
(dnd-handle-one-url window 'private (concat "file:" data)))
(defun ns-drag-n-drop-other-frame (event) (dnd-insert-text window 'private string)))
"Edit the files listed in the drag-n-drop EVENT, in other frames. ((memq 'ns-drag-operation-copy operations)
May create new frames, or reuse existing ones. The frame editing ;; Try to open the file/URL. If type is nil, try to open
the last file dropped is selected." ;; it as a URL anyway.
(interactive "e") (dolist (data objects)
(ns-drag-n-drop event t)) (dnd-handle-one-url window 'private (if (eq type 'file)
(concat "file:" data)
(defun ns-drag-n-drop-as-text (event) data))))
"Drop the data in EVENT as text." (t
(interactive "e") ;; Insert the text as is.
(ns-drag-n-drop event nil t)) (dnd-insert-text window 'private string)))))
(defun ns-drag-n-drop-as-text-other-frame (event)
"Drop the data in EVENT as text in a new frame."
(interactive "e")
(ns-drag-n-drop event t t))
(global-set-key [drag-n-drop] 'ns-drag-n-drop) (global-set-key [drag-n-drop] 'ns-drag-n-drop)
(global-set-key [C-drag-n-drop] 'ns-drag-n-drop-other-frame)
(global-set-key [M-drag-n-drop] 'ns-drag-n-drop-as-text)
(global-set-key [C-M-drag-n-drop] 'ns-drag-n-drop-as-text-other-frame)
;;;; Frame-related functions. ;;;; Frame-related functions.
......
...@@ -8230,7 +8230,9 @@ -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender ...@@ -8230,7 +8230,9 @@ -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
NSEvent *theEvent = [[self window] currentEvent]; NSEvent *theEvent = [[self window] currentEvent];
NSPoint position; NSPoint position;
NSDragOperation op = [sender draggingSourceOperationMask]; NSDragOperation op = [sender draggingSourceOperationMask];
int modifiers = 0; Lisp_Object operations = Qnil;
Lisp_Object strings = Qnil;
Lisp_Object type_sym;
NSTRACE ("[EmacsView performDragOperation:]"); NSTRACE ("[EmacsView performDragOperation:]");
...@@ -8243,19 +8245,17 @@ -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender ...@@ -8243,19 +8245,17 @@ -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
pb = [sender draggingPasteboard]; pb = [sender draggingPasteboard];
type = [pb availableTypeFromArray: ns_drag_types]; type = [pb availableTypeFromArray: ns_drag_types];
if (! (op & (NSDragOperationMove|NSDragOperationDelete)) && /* We used to convert these drag operations to keyboard modifiers,
// URL drags contain all operations (0xf), don't allow all to be set. but because they can be set by the sending program as well as the
(op & 0xf) != 0xf) keyboard modifiers it was difficult to work out a sensible key
{ mapping for drag and drop. */
if (op & NSDragOperationLink) if (op & NSDragOperationLink)
modifiers |= NSEventModifierFlagControl; operations = Fcons (Qns_drag_operation_link, operations);
if (op & NSDragOperationCopy) if (op & NSDragOperationCopy)
modifiers |= NSEventModifierFlagOption; operations = Fcons (Qns_drag_operation_copy, operations);
if (op & NSDragOperationGeneric) if (op & NSDragOperationGeneric || NILP (operations))
modifiers |= NSEventModifierFlagCommand; operations = Fcons (Qns_drag_operation_generic, operations);
}
modifiers = EV_MODIFIERS2 (modifiers);
if (type == 0) if (type == 0)
{ {
return NO; return NO;
...@@ -8269,39 +8269,20 @@ -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender ...@@ -8269,39 +8269,20 @@ -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
if (!(files = [pb propertyListForType: type])) if (!(files = [pb propertyListForType: type]))
return NO; return NO;
type_sym = Qfile;
fenum = [files objectEnumerator]; fenum = [files objectEnumerator];
while ( (file = [fenum nextObject]) ) while ( (file = [fenum nextObject]) )
{ strings = Fcons (build_string ([file UTF8String]), strings);
emacs_event->kind = DRAG_N_DROP_EVENT;
XSETINT (emacs_event->x, x);
XSETINT (emacs_event->y, y);
emacs_event->modifiers = modifiers;
emacs_event->arg = list2 (Qfile, build_string ([file UTF8String]));
EV_TRAILER (theEvent);
}
return YES;
} }
else if ([type isEqualToString: NSURLPboardType]) else if ([type isEqualToString: NSURLPboardType])
{ {
NSURL *url = [NSURL URLFromPasteboard: pb]; NSURL *url = [NSURL URLFromPasteboard: pb];
if (url == nil) return NO; if (url == nil) return NO;
emacs_event->kind = DRAG_N_DROP_EVENT; type_sym = Qurl;
XSETINT (emacs_event->x, x);
XSETINT (emacs_event->y, y);
emacs_event->modifiers = modifiers;
emacs_event->arg = list2 (Qurl,
build_string ([[url absoluteString]
UTF8String]));
EV_TRAILER (theEvent);
if ([url isFileURL] != NO) strings = Fcons (build_string ([[url absoluteString] UTF8String]), Qnil);
{
NSString *file = [url path];
ns_input_file = append2 (ns_input_file,
build_string ([file UTF8String]));
}
return YES;
} }
else if ([type isEqualToString: NSStringPboardType] else if ([type isEqualToString: NSStringPboardType]
|| [type isEqualToString: NSTabularTextPboardType]) || [type isEqualToString: NSTabularTextPboardType])
...@@ -8311,19 +8292,27 @@ -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender ...@@ -8311,19 +8292,27 @@ -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
if (! (data = [pb stringForType: type])) if (! (data = [pb stringForType: type]))
return NO; return NO;
emacs_event->kind = DRAG_N_DROP_EVENT; type_sym = Qnil;
XSETINT (emacs_event->x, x);
XSETINT (emacs_event->y, y); strings = Fcons (build_string ([data UTF8String]), Qnil);
emacs_event->modifiers = modifiers;
emacs_event->arg = list2 (Qnil, build_string ([data UTF8String]));
EV_TRAILER (theEvent);
return YES;
} }
else else
{ {
fprintf (stderr, "Invalid data type in dragging pasteboard"); fprintf (stderr, "Invalid data type in dragging pasteboard");
return NO; return NO;
} }
emacs_event->kind = DRAG_N_DROP_EVENT;
XSETINT (emacs_event->x, x);
XSETINT (emacs_event->y, y);
emacs_event->modifiers = 0;
emacs_event->arg = Fcons (type_sym,
Fcons (operations,
strings));
EV_TRAILER (theEvent);
return YES;
} }
...@@ -9358,6 +9347,10 @@ Convert an X font name (XLFD) to an NS font name. ...@@ -9358,6 +9347,10 @@ Convert an X font name (XLFD) to an NS font name.
DEFSYM (Qfile, "file"); DEFSYM (Qfile, "file");
DEFSYM (Qurl, "url"); DEFSYM (Qurl, "url");
DEFSYM (Qns_drag_operation_copy, "ns-drag-operation-copy");
DEFSYM (Qns_drag_operation_link, "ns-drag-operation-link");
DEFSYM (Qns_drag_operation_generic, "ns-drag-operation-generic");
Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier)); Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier));
Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier)); Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier)); Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment