summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Third <alan@idiocy.org>2019-01-05 16:11:37 +0000
committerAlan Third <alan@idiocy.org>2019-01-10 19:24:19 +0000
commitc342b26371480316024e1e5d63cd8b3f035dda69 (patch)
treeec999f6d48e5737528f48f9c0224de5db8a13d10
parent7ae0a24c87c2bbefe78717d5e89cf3fe14f4af4c (diff)
downloademacs-c342b26371480316024e1e5d63cd8b3f035dda69.tar.gz
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.
-rw-r--r--doc/emacs/macos.texi21
-rw-r--r--etc/NEWS6
-rw-r--r--lisp/term/ns-win.el54
-rw-r--r--src/nsterm.m81
4 files changed, 84 insertions, 78 deletions
diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi
index 6d27e978217..d9920957ad7 100644
--- a/doc/emacs/macos.texi
+++ b/doc/emacs/macos.texi
@@ -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
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
-the mouse. It may sometimes be necessary to use the @key{Meta} key in
-conjunction with dragging to force text insertion.
+the mouse.
+
+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
This event occurs when the user selects a font in a Nextstep font
diff --git a/etc/NEWS b/etc/NEWS
index 3d49640ac5d..a3aa5a29381 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -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
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.
diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el
index c9f5bfef520..6a668b213dd 100644
--- a/lisp/term/ns-win.el
+++ b/lisp/term/ns-win.el
@@ -501,48 +501,38 @@ unless the current buffer is a scratch buffer."
(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.
-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")
(let* ((window (posn-window (event-start event)))
(arg (car (cdr (cdr event))))
(type (car arg))
- (data (car (cdr arg)))
- (url-or-string (cond ((eq type 'file)
- (concat "file:" data))
- (t data))))
+ (operations (car (cdr arg)))
+ (objects (cdr (cdr arg)))
+ (string (mapconcat 'identity objects "\n")))
(set-frame-selected-window nil window)
- (when new-frame
- (select-frame (make-frame)))
(raise-frame)
(setq window (selected-window))
- (if force-text
- (dnd-insert-text window 'private data)
- (dnd-handle-one-url window 'private url-or-string))))
-
-
-(defun ns-drag-n-drop-other-frame (event)
- "Edit the files listed in the drag-n-drop EVENT, in other frames.
-May create new frames, or reuse existing ones. The frame editing
-the last file dropped is selected."
- (interactive "e")
- (ns-drag-n-drop event t))
-
-(defun ns-drag-n-drop-as-text (event)
- "Drop the data in EVENT as text."
- (interactive "e")
- (ns-drag-n-drop event nil t))
-
-(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))
+ (cond ((memq 'ns-drag-operation-generic operations)
+ ;; Perform the default action for the type.
+ (if (eq type 'file)
+ (dolist (data objects)
+ (dnd-handle-one-url window 'private (concat "file:" data)))
+ (dnd-insert-text window 'private string)))
+ ((memq 'ns-drag-operation-copy operations)
+ ;; Try to open the file/URL. If type is nil, try to open
+ ;; it as a URL anyway.
+ (dolist (data objects)
+ (dnd-handle-one-url window 'private (if (eq type 'file)
+ (concat "file:" data)
+ data))))
+ (t
+ ;; Insert the text as is.
+ (dnd-insert-text window 'private string)))))
(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.
diff --git a/src/nsterm.m b/src/nsterm.m
index 016c0447609..2bce4a89aea 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -8230,7 +8230,9 @@ not_in_argv (NSString *arg)
NSEvent *theEvent = [[self window] currentEvent];
NSPoint position;
NSDragOperation op = [sender draggingSourceOperationMask];
- int modifiers = 0;
+ Lisp_Object operations = Qnil;
+ Lisp_Object strings = Qnil;
+ Lisp_Object type_sym;
NSTRACE ("[EmacsView performDragOperation:]");
@@ -8243,19 +8245,17 @@ not_in_argv (NSString *arg)
pb = [sender draggingPasteboard];
type = [pb availableTypeFromArray: ns_drag_types];
- if (! (op & (NSDragOperationMove|NSDragOperationDelete)) &&
- // URL drags contain all operations (0xf), don't allow all to be set.
- (op & 0xf) != 0xf)
- {
- if (op & NSDragOperationLink)
- modifiers |= NSEventModifierFlagControl;
- if (op & NSDragOperationCopy)
- modifiers |= NSEventModifierFlagOption;
- if (op & NSDragOperationGeneric)
- modifiers |= NSEventModifierFlagCommand;
- }
+ /* We used to convert these drag operations to keyboard modifiers,
+ but because they can be set by the sending program as well as the
+ keyboard modifiers it was difficult to work out a sensible key
+ mapping for drag and drop. */
+ if (op & NSDragOperationLink)
+ operations = Fcons (Qns_drag_operation_link, operations);
+ if (op & NSDragOperationCopy)
+ operations = Fcons (Qns_drag_operation_copy, operations);
+ if (op & NSDragOperationGeneric || NILP (operations))
+ operations = Fcons (Qns_drag_operation_generic, operations);
- modifiers = EV_MODIFIERS2 (modifiers);
if (type == 0)
{
return NO;
@@ -8269,39 +8269,20 @@ not_in_argv (NSString *arg)
if (!(files = [pb propertyListForType: type]))
return NO;
+ type_sym = Qfile;
+
fenum = [files objectEnumerator];
while ( (file = [fenum nextObject]) )
- {
- 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;
+ strings = Fcons (build_string ([file UTF8String]), strings);
}
else if ([type isEqualToString: NSURLPboardType])
{
NSURL *url = [NSURL URLFromPasteboard: pb];
if (url == nil) return NO;
- 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 (Qurl,
- build_string ([[url absoluteString]
- UTF8String]));
- EV_TRAILER (theEvent);
+ type_sym = Qurl;
- if ([url isFileURL] != NO)
- {
- NSString *file = [url path];
- ns_input_file = append2 (ns_input_file,
- build_string ([file UTF8String]));
- }
- return YES;
+ strings = Fcons (build_string ([[url absoluteString] UTF8String]), Qnil);
}
else if ([type isEqualToString: NSStringPboardType]
|| [type isEqualToString: NSTabularTextPboardType])
@@ -8311,19 +8292,27 @@ not_in_argv (NSString *arg)
if (! (data = [pb stringForType: type]))
return NO;
- 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 (Qnil, build_string ([data UTF8String]));
- EV_TRAILER (theEvent);
- return YES;
+ type_sym = Qnil;
+
+ strings = Fcons (build_string ([data UTF8String]), Qnil);
}
else
{
fprintf (stderr, "Invalid data type in dragging pasteboard");
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 @@ syms_of_nsterm (void)
DEFSYM (Qfile, "file");
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 (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier));
Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier));