From: Jan Djärv Date: Thu, 19 Dec 2013 10:25:48 +0000 (+0100) Subject: Make NS port use the normal dnd functions. X-Git-Tag: emacs-24.3.90~173^2^2~42^2~45^2~387^2~327 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=1269a680862a9bc6cd65e3d26ef05f68c7521632;p=emacs.git Make NS port use the normal dnd functions. * lisp/term/ns-win.el: Require dnd. (global-map): Remove drag items. (ns-insert-text, ns-set-foreground-at-mouse) (ns-set-background-at-mouse): Remove (ns-drag-n-drop, ns-drag-n-drop-other-frame) (ns-drag-n-drop-as-text, ns-drag-n-drop-as-text-other-frame): New functions. * src/nsterm.h (KEY_NS_DRAG_FILE, KEY_NS_DRAG_COLOR, KEY_NS_DRAG_TEXT): Remove. * src/nsterm.m (Qfile, Qurl): New. (EV_MODIFIERS2): New macro. (EV_MODIFIERS): Use EV_MODIFIERS2. (ns_term_init): Remove font and color from DND, does not work on newer OSX, and other ports don't have them. (performDragOperation:): Handle modifiers used during drag. Use DRAG_N_DROP_EVENT instead of NS specific events. Remove global Lisp variables used to communicate with ns-win.el. Remove font and color handling. (syms_of_nsterm): Defsym Qfile and Qurl. Fixes: debbugs:8051 --- diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 249f629b5f4..336a7caa8ed 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,13 @@ +2013-12-19 Jan Djärv + + * term/ns-win.el: Require dnd. + (global-map): Remove drag items. + (ns-insert-text, ns-set-foreground-at-mouse) + (ns-set-background-at-mouse): Remove + (ns-drag-n-drop, ns-drag-n-drop-other-frame) + (ns-drag-n-drop-as-text, ns-drag-n-drop-as-text-other-frame): New + functions. + 2013-12-19 Glenn Morris * emacs-lisp/ert.el (ert-select-tests): diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index 03244aaeb8a..f780fbfc2fe 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -50,6 +50,7 @@ (require 'faces) (require 'menu-bar) (require 'fontset) +(require 'dnd) (defgroup ns nil "GNUstep/Mac OS X specific features." @@ -160,10 +161,6 @@ The properties returned may include `top', `left', `height', and `width'." (define-key global-map [ns-power-off] 'save-buffers-kill-emacs) (define-key global-map [ns-open-file] 'ns-find-file) (define-key global-map [ns-open-temp-file] [ns-open-file]) -(define-key global-map [ns-drag-file] 'ns-find-file) -(define-key global-map [ns-drag-color] 'ns-set-foreground-at-mouse) -(define-key global-map [S-ns-drag-color] 'ns-set-background-at-mouse) -(define-key global-map [ns-drag-text] 'ns-insert-text) (define-key global-map [ns-change-font] 'ns-respond-to-change-font) (define-key global-map [ns-open-file-line] 'ns-open-file-select-line) (define-key global-map [ns-spi-service-call] 'ns-spi-service-call) @@ -365,14 +362,6 @@ See `ns-insert-working-text'." ;;;; Inter-app communications support. -(defvar ns-input-text) ; nsterm.m - -(defun ns-insert-text () - "Insert contents of `ns-input-text' at point." - (interactive) - (insert ns-input-text) - (setq ns-input-text nil)) - (defun ns-insert-file () "Insert contents of file `ns-input-file' like insert-file but with less prompting. If file is a directory perform a `find-file' on it." @@ -518,6 +507,50 @@ unless the current buffer is a scratch buffer." (ns-hide-emacs 'activate) (find-file f))))) + +(defun ns-drag-n-drop (event &optional new-frame force-text) + "Edit the files listed in the drag-n-drop EVENT. +Switch to a buffer editing the last file dropped." + (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)))) + (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)) + +(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. ;; nsterm.m @@ -830,40 +863,6 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (t nil)))) -(defvar ns-input-color) ; nsterm.m - -(defun ns-set-foreground-at-mouse () - "Set the foreground color at the mouse location to `ns-input-color'." - (interactive) - (let* ((pos (mouse-position)) - (frame (car pos)) - (face (ns-face-at-pos pos))) - (cond - ((eq face 'cursor) - (modify-frame-parameters frame (list (cons 'cursor-color - ns-input-color)))) - ((not face) - (modify-frame-parameters frame (list (cons 'foreground-color - ns-input-color)))) - (t - (set-face-foreground face ns-input-color frame))))) - -(defun ns-set-background-at-mouse () - "Set the background color at the mouse location to `ns-input-color'." - (interactive) - (let* ((pos (mouse-position)) - (frame (car pos)) - (face (ns-face-at-pos pos))) - (cond - ((eq face 'cursor) - (modify-frame-parameters frame (list (cons 'cursor-color - ns-input-color)))) - ((not face) - (modify-frame-parameters frame (list (cons 'background-color - ns-input-color)))) - (t - (set-face-background face ns-input-color frame))))) - ;; Set some options to be as Nextstep-like as possible. (setq frame-title-format t icon-title-format t) diff --git a/src/ChangeLog b/src/ChangeLog index e7f30f25800..283777cbcdf 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,19 @@ +2013-12-19 Jan Djärv + + * nsterm.h (KEY_NS_DRAG_FILE, KEY_NS_DRAG_COLOR, KEY_NS_DRAG_TEXT): + Remove. + + * nsterm.m (Qfile, Qurl): New. + (EV_MODIFIERS2): New macro. + (EV_MODIFIERS): Use EV_MODIFIERS2. + (ns_term_init): Remove font and color from DND, does not work on + newer OSX, and other ports don't have them. + (performDragOperation:): Handle modifiers used during drag. + Use DRAG_N_DROP_EVENT instead of NS specific events (Bug#8051). + Remove global Lisp variables used to communicate with ns-win.el. + Remove font and color handling. + (syms_of_nsterm): Defsym Qfile and Qurl. + 2013-12-19 Anders Lindgren * nsterm.m (NSTRACE_SIZE, NSTRACE_RECT): New macros. diff --git a/src/nsterm.h b/src/nsterm.h index faf8271bcc7..b86122417e5 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -458,9 +458,6 @@ extern EmacsMenu *mainMenu, *svcsMenu, *dockMenu; #define KEY_NS_POWER_OFF ((1<<28)|(0<<16)|1) #define KEY_NS_OPEN_FILE ((1<<28)|(0<<16)|2) #define KEY_NS_OPEN_TEMP_FILE ((1<<28)|(0<<16)|3) -#define KEY_NS_DRAG_FILE ((1<<28)|(0<<16)|4) -#define KEY_NS_DRAG_COLOR ((1<<28)|(0<<16)|5) -#define KEY_NS_DRAG_TEXT ((1<<28)|(0<<16)|6) #define KEY_NS_CHANGE_FONT ((1<<28)|(0<<16)|7) #define KEY_NS_OPEN_FILE_LINE ((1<<28)|(0<<16)|8) #define KEY_NS_PUT_WORKING_TEXT ((1<<28)|(0<<16)|9) diff --git a/src/nsterm.m b/src/nsterm.m index d7c2f38135a..8047bca1f60 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -80,7 +80,7 @@ int term_trace_num = 0; #endif /* Detailed tracing. "S" means "size" and "LL" stands for "lower left". */ -#if 1 +#if 0 int term_trace_num = 0; #define NSTRACE_SIZE(str,size) fprintf (stderr, \ "%s:%d: [%d] " str \ @@ -196,6 +196,7 @@ extern Lisp_Object Qcursor_color, Qcursor_type, Qns, Qleft; static Lisp_Object QUTF8_STRING; static Lisp_Object Qcocoa, Qgnustep; +static Lisp_Object Qfile, Qurl; /* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold, the maximum font size to NOT antialias. On GNUstep there is currently @@ -278,31 +279,32 @@ static CGPoint menu_mouse_point; #define NSRightCommandKeyMask (0x000010 | NSCommandKeyMask) #define NSLeftAlternateKeyMask (0x000020 | NSAlternateKeyMask) #define NSRightAlternateKeyMask (0x000040 | NSAlternateKeyMask) -#define EV_MODIFIERS(e) \ - ((([e modifierFlags] & NSHelpKeyMask) ? \ +#define EV_MODIFIERS2(flags) \ + (((flags & NSHelpKeyMask) ? \ hyper_modifier : 0) \ | (!EQ (ns_right_alternate_modifier, Qleft) && \ - (([e modifierFlags] & NSRightAlternateKeyMask) \ + ((flags & NSRightAlternateKeyMask) \ == NSRightAlternateKeyMask) ? \ parse_solitary_modifier (ns_right_alternate_modifier) : 0) \ - | (([e modifierFlags] & NSAlternateKeyMask) ? \ + | ((flags & NSAlternateKeyMask) ? \ parse_solitary_modifier (ns_alternate_modifier) : 0) \ - | (([e modifierFlags] & NSShiftKeyMask) ? \ + | ((flags & NSShiftKeyMask) ? \ shift_modifier : 0) \ | (!EQ (ns_right_control_modifier, Qleft) && \ - (([e modifierFlags] & NSRightControlKeyMask) \ + ((flags & NSRightControlKeyMask) \ == NSRightControlKeyMask) ? \ parse_solitary_modifier (ns_right_control_modifier) : 0) \ - | (([e modifierFlags] & NSControlKeyMask) ? \ + | ((flags & NSControlKeyMask) ? \ parse_solitary_modifier (ns_control_modifier) : 0) \ - | (([e modifierFlags] & NS_FUNCTION_KEY_MASK) ? \ + | ((flags & NS_FUNCTION_KEY_MASK) ? \ parse_solitary_modifier (ns_function_modifier) : 0) \ | (!EQ (ns_right_command_modifier, Qleft) && \ - (([e modifierFlags] & NSRightCommandKeyMask) \ + ((flags & NSRightCommandKeyMask) \ == NSRightCommandKeyMask) ? \ parse_solitary_modifier (ns_right_command_modifier) : 0) \ - | (([e modifierFlags] & NSCommandKeyMask) ? \ + | ((flags & NSCommandKeyMask) ? \ parse_solitary_modifier (ns_command_modifier):0)) +#define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags]) #define EV_UDMODIFIERS(e) \ ((([e type] == NSLeftMouseDown) ? down_modifier : 0) \ @@ -4377,9 +4379,7 @@ ns_term_init (Lisp_Object display_name) NSStringPboardType, NSTabularTextPboardType, NSFilenamesPboardType, - NSURLPboardType, - NSColorPboardType, - NSFontPboardType, nil] retain]; + NSURLPboardType, nil] retain]; /* If fullscreen is in init/default-frame-alist, focus isn't set right for fullscreen windows, so set this. */ @@ -6647,6 +6647,8 @@ if (cols > 0 && rows > 0) NSString *type; NSEvent *theEvent = [[self window] currentEvent]; NSPoint position; + NSDragOperation op = [sender draggingSourceOperationMask]; + int modifiers = 0; NSTRACE (performDragOperation); @@ -6658,6 +6660,20 @@ if (cols > 0 && rows > 0) 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 |= NSControlKeyMask; + if (op & NSDragOperationCopy) + modifiers |= NSAlternateKeyMask; + if (op & NSDragOperationGeneric) + modifiers |= NSCommandKeyMask; + } + + modifiers = EV_MODIFIERS2 (modifiers); if (type == 0) { return NO; @@ -6674,34 +6690,37 @@ if (cols > 0 && rows > 0) fenum = [files objectEnumerator]; while ( (file = [fenum nextObject]) ) { - emacs_event->kind = NS_NONKEY_EVENT; - emacs_event->code = KEY_NS_DRAG_FILE; + emacs_event->kind = DRAG_N_DROP_EVENT; XSETINT (emacs_event->x, x); XSETINT (emacs_event->y, y); ns_input_file = append2 (ns_input_file, build_string ([file UTF8String])); - emacs_event->modifiers = EV_MODIFIERS (theEvent); + emacs_event->modifiers = modifiers; + emacs_event->arg = list2 (Qfile, build_string ([file UTF8String])); EV_TRAILER (theEvent); } return YES; } else if ([type isEqualToString: NSURLPboardType]) { - NSString *file; - NSURL *fileURL; - - if (!(fileURL = [NSURL URLFromPasteboard: pb]) || - [fileURL isFileURL] == NO) - return NO; + NSURL *url = [NSURL URLFromPasteboard: pb]; + if (url == nil) return NO; - file = [fileURL path]; - emacs_event->kind = NS_NONKEY_EVENT; - emacs_event->code = KEY_NS_DRAG_FILE; + emacs_event->kind = DRAG_N_DROP_EVENT; XSETINT (emacs_event->x, x); XSETINT (emacs_event->y, y); - ns_input_file = append2 (ns_input_file, build_string ([file UTF8String])); - emacs_event->modifiers = EV_MODIFIERS (theEvent); + emacs_event->modifiers = modifiers; + emacs_event->arg = list2 (Qurl, + build_string ([[url absoluteString] + UTF8String])); EV_TRAILER (theEvent); + + if ([url isFileURL] != NO) + { + NSString *file = [url path]; + ns_input_file = append2 (ns_input_file, + build_string ([file UTF8String])); + } return YES; } else if ([type isEqualToString: NSStringPboardType] @@ -6712,46 +6731,11 @@ if (cols > 0 && rows > 0) if (! (data = [pb stringForType: type])) return NO; - emacs_event->kind = NS_NONKEY_EVENT; - emacs_event->code = KEY_NS_DRAG_TEXT; - XSETINT (emacs_event->x, x); - XSETINT (emacs_event->y, y); - ns_input_text = build_string ([data UTF8String]); - emacs_event->modifiers = EV_MODIFIERS (theEvent); - EV_TRAILER (theEvent); - return YES; - } - else if ([type isEqualToString: NSColorPboardType]) - { - NSColor *c = [NSColor colorFromPasteboard: pb]; - emacs_event->kind = NS_NONKEY_EVENT; - emacs_event->code = KEY_NS_DRAG_COLOR; - XSETINT (emacs_event->x, x); - XSETINT (emacs_event->y, y); - ns_input_color = ns_color_to_lisp (c); - emacs_event->modifiers = EV_MODIFIERS (theEvent); - EV_TRAILER (theEvent); - return YES; - } - else if ([type isEqualToString: NSFontPboardType]) - { - /* impl based on GNUstep NSTextView.m */ - NSData *data = [pb dataForType: NSFontPboardType]; - NSDictionary *dict = [NSUnarchiver unarchiveObjectWithData: data]; - NSFont *font = [dict objectForKey: NSFontAttributeName]; - char fontSize[10]; - - if (font == nil) - return NO; - - emacs_event->kind = NS_NONKEY_EVENT; - emacs_event->code = KEY_NS_CHANGE_FONT; + emacs_event->kind = DRAG_N_DROP_EVENT; XSETINT (emacs_event->x, x); XSETINT (emacs_event->y, y); - ns_input_font = build_string ([[font fontName] UTF8String]); - snprintf (fontSize, 10, "%f", [font pointSize]); - ns_input_fontsize = build_string (fontSize); - emacs_event->modifiers = EV_MODIFIERS (theEvent); + emacs_event->modifiers = modifiers; + emacs_event->arg = list2 (Qnil, build_string ([data UTF8String])); EV_TRAILER (theEvent); return YES; } @@ -7514,6 +7498,9 @@ syms_of_nsterm (void) DEFSYM (Qcontrol, "control"); DEFSYM (QUTF8_STRING, "UTF8_STRING"); + DEFSYM (Qfile, "file"); + DEFSYM (Qurl, "url"); + Fput (Qalt, Qmodifier_value, make_number (alt_modifier)); Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier)); Fput (Qmeta, Qmodifier_value, make_number (meta_modifier)); @@ -7524,10 +7511,6 @@ syms_of_nsterm (void) "The file specified in the last NS event."); ns_input_file =Qnil; - DEFVAR_LISP ("ns-input-text", ns_input_text, - "The data received in the last NS text drag event."); - ns_input_text =Qnil; - DEFVAR_LISP ("ns-working-text", ns_working_text, "String for visualizing working composition sequence."); ns_working_text =Qnil; @@ -7544,10 +7527,6 @@ syms_of_nsterm (void) "The line specified in the last NS event."); ns_input_line =Qnil; - DEFVAR_LISP ("ns-input-color", ns_input_color, - "The color specified in the last NS event."); - ns_input_color =Qnil; - DEFVAR_LISP ("ns-input-spi-name", ns_input_spi_name, "The service name specified in the last NS event."); ns_input_spi_name =Qnil;