From 1afb1d071576f7884a475c04955fc33126f70221 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jan=20Dj=C3=A4rv?= Date: Sat, 6 Jul 2013 19:58:41 +0200 Subject: [PATCH] * lisp/files.el (write-file): Do not display confirm dialog for NS, it does its own dialog, which can't be cancelled. * src/nsfns.m: Remove panelOK. (ns_fd_data): New. (ns_run_file_dialog): New function. (Fns_read_file_name): Fill in ns_fd_data, post an event and start the event loop, so file dialog is popped up by ns_run_file_dialog, called by sendEvent (Bug#14578). (EmacsSavePanel, EmacsOpenPanel): Remove ok and cancel methods. * src/nsterm.h (NSSavePanel): Update comment. (NSAPP_DATA2_RUNFILEDIALOG): Define. (ns_run_file_dialog): Declare. * src/nsterm.m (sendEvent:): Handle NSAPP_DATA2_RUNFILEDIALOG. --- lisp/ChangeLog | 5 ++ lisp/files.el | 4 ++ src/ChangeLog | 16 +++++++ src/nsfns.m | 121 +++++++++++++++++++++++++------------------------ src/nsterm.h | 6 ++- src/nsterm.m | 21 ++++++--- 6 files changed, 105 insertions(+), 68 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index a4ee883f518..2402ea0cd1f 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2013-07-06 Jan Djärv + + * files.el (write-file): Do not display confirm dialog for NS, + it does its own dialog, which can't be cancelled (Bug#14578). + 2013-07-06 Eli Zaretskii * simple.el (line-move-partial): Adjust the row returned by diff --git a/lisp/files.el b/lisp/files.el index e59a9acb7b9..9b56dfa9693 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -3878,6 +3878,10 @@ Interactively, confirmation is required unless you supply a prefix argument." (or buffer-file-name (buffer-name)))))) (and confirm (file-exists-p filename) + ;; NS does its own confirm dialog. + (not (and (eq (framep-on-display) 'ns) + (listp last-nonmenu-event) + use-dialog-box)) (or (y-or-n-p (format "File `%s' exists; overwrite? " filename)) (error "Canceled"))) (set-visited-file-name filename (not confirm)))) diff --git a/src/ChangeLog b/src/ChangeLog index 9bf1840baac..b95488c1e70 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,19 @@ +2013-07-06 Jan Djärv + + * nsterm.m (sendEvent:): Handle NSAPP_DATA2_RUNFILEDIALOG. + + * nsterm.h (NSSavePanel): Update comment. + (NSAPP_DATA2_RUNFILEDIALOG): Define. + (ns_run_file_dialog): Declare. + + * nsfns.m: Remove panelOK. + (ns_fd_data): New. + (ns_run_file_dialog): New function. + (Fns_read_file_name): Fill in ns_fd_data, post an event and start the + event loop, so file dialog is popped up by ns_run_file_dialog, called + by sendEvent (Bug#14578). + (EmacsSavePanel, EmacsOpenPanel): Remove ok and cancel methods. + 2013-07-06 Eli Zaretskii * xdisp.c (default_line_pixel_height): New function. diff --git a/src/nsfns.m b/src/nsfns.m index 1e075995c11..b8f46e461fa 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -89,9 +89,6 @@ extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle; Lisp_Object Qbuffered; Lisp_Object Qfontsize; -/* hack for OS X file panels */ -char panelOK = 0; - EmacsTooltip *ns_tooltip = nil; /* Need forward declaration here to preserve organizational integrity of file */ @@ -1396,6 +1393,41 @@ DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel, return Qnil; } +static struct +{ + id panel; + BOOL ret; +#if ! defined (NS_IMPL_COCOA) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 + NSString *dirS, *initS; + BOOL no_types; +#endif +} ns_fd_data; + +void +ns_run_file_dialog (void) +{ + if (ns_fd_data.panel == nil) return; +#if defined (NS_IMPL_COCOA) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + ns_fd_data.ret = [ns_fd_data.panel runModal]; +#else + if (ns_fd_data.no_types) + { + ns_fd_data.ret = [ns_fd_data.panel + runModalForDirectory: ns_fd_data.dirS + file: ns_fd_data.initS]; + } + else + { + ns_fd_data.ret = [ns_fd_data.panel + runModalForDirectory: ns_fd_data.dirS + file: ns_fd_data.initS + types: nil]; + } +#endif + ns_fd_data.panel = nil; +} DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 5, 0, doc: /* Use a graphical panel to read a file name, using prompt PROMPT. @@ -1420,6 +1452,7 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) [NSString stringWithUTF8String: SSDATA (dir)]; NSString *initS = NILP (init) || !STRINGP (init) ? nil : [NSString stringWithUTF8String: SSDATA (init)]; + NSEvent *nxev; check_window_system (NULL); @@ -1440,7 +1473,6 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) [panel setTreatsFilePackagesAsDirectories: YES]; [panel setDelegate: fileDelegate]; - panelOK = 0; if (! NILP (dir_only_p)) { [panel setCanChooseDirectories: YES]; @@ -1454,7 +1486,9 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) [panel setCanChooseFiles: YES]; } - block_input (); + block_input (); + ns_fd_data.panel = panel; + ns_fd_data.ret = NO; #if defined (NS_IMPL_COCOA) && \ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 if (! NILP (mustmatch) || ! NILP (dir_only_p)) @@ -1465,19 +1499,32 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) else [panel setNameFieldStringValue: @""]; - ret = [panel runModal]; #else - if (NILP (mustmatch) && NILP (dir_only_p)) - { - ret = [panel runModalForDirectory: dirS file: initS]; - } - else - { - ret = [panel runModalForDirectory: dirS file: initS types: nil]; - } + ns_fd_data.no_types = NILP (mustmatch) && NILP (dir_only_p); + ns_fd_data.dirS = dirS; + ns_fd_data.initS = initS; #endif - ret = (ret == NSOKButton) || panelOK; + /* runModalForDirectory/runModal restarts the main event loop when done, + so we must start an event loop and then pop up the file dialog. + The file dialog may pop up a confirm dialog after Ok has been pressed, + so we can not simply pop down on the Ok/Cancel press. + */ + nxev = [NSEvent otherEventWithType: NSApplicationDefined + location: NSMakePoint (0, 0) + modifierFlags: 0 + timestamp: 0 + windowNumber: [[NSApp mainWindow] windowNumber] + context: [NSApp context] + subtype: 0 + data1: 0 + data2: NSAPP_DATA2_RUNFILEDIALOG]; + + [NSApp postEvent: nxev atStart: NO]; + while (ns_fd_data.panel != nil) + [NSApp run]; + + ret = (ns_fd_data.ret == NSOKButton); if (ret) { @@ -2755,25 +2802,6 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) } @implementation EmacsSavePanel -#ifdef NS_IMPL_COCOA -/* -------------------------------------------------------------------------- - These are overridden to intercept on OS X: ending panel restarts NSApp - event loop if it is stopped. Not sure if this is correct behavior, - perhaps should check if running and if so send an appdefined. - -------------------------------------------------------------------------- */ -- (void) ok: (id)sender -{ - [super ok: sender]; - panelOK = 1; - [NSApp stop: self]; -} -- (void) cancel: (id)sender -{ - [super cancel: sender]; - [NSApp stop: self]; -} -#endif - - (BOOL)performKeyEquivalent:(NSEvent *)theEvent { BOOL ret = handlePanelKeys (self, theEvent); @@ -2785,31 +2813,6 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) @implementation EmacsOpenPanel -#ifdef NS_IMPL_COCOA -/* -------------------------------------------------------------------------- - These are overridden to intercept on OS X: ending panel restarts NSApp - event loop if it is stopped. Not sure if this is correct behavior, - perhaps should check if running and if so send an appdefined. - -------------------------------------------------------------------------- */ -- (void) ok: (id)sender -{ - [super ok: sender]; - - // If not choosing directories, and Open is pressed on a directory, return. - if (! [self canChooseDirectories] && ns_directory_from_panel (self) && - ! ns_filename_from_panel (self)) - return; - - panelOK = 1; - [NSApp stop: self]; -} -- (void) cancel: (id)sender -{ - [super cancel: sender]; - [NSApp stop: self]; -} - -#endif - (BOOL)performKeyEquivalent:(NSEvent *)theEvent { // NSOpenPanel inherits NSSavePanel, so passing self is OK. diff --git a/src/nsterm.h b/src/nsterm.h index fd8c9baa3e4..745b8a4145b 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -286,8 +286,7 @@ typedef float EmacsCGFloat; /* ========================================================================== File open/save panels - This and next override methods to work around OS X behavior of - restarting application loop when user dismisses panel. + This and next override methods to handle keyboard input in panels. ========================================================================== */ @@ -838,6 +837,9 @@ extern Lisp_Object ns_popup_dialog (Lisp_Object position, Lisp_Object contents, #define NSAPP_DATA2_RUNASSCRIPT 10 extern void ns_run_ascript (void); +#define NSAPP_DATA2_RUNFILEDIALOG 11 +extern void ns_run_file_dialog (void); + extern const char *ns_etc_directory (void); extern const char *ns_exec_path (void); extern const char *ns_load_path (void); diff --git a/src/nsterm.m b/src/nsterm.m index 93f693fe55e..97a6313489d 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -4419,15 +4419,22 @@ ns_term_shutdown (int sig) /* NSTRACE (sendEvent); */ /*fprintf (stderr, "received event of type %d\t%d\n", type);*/ -#ifdef NS_IMPL_COCOA - if (type == NSApplicationDefined - && [theEvent data2] == NSAPP_DATA2_RUNASSCRIPT) + if (type == NSApplicationDefined) { - ns_run_ascript (); - [self stop: self]; - return; - } + switch ([theEvent data2]) + { +#ifdef NS_IMPL_COCOA + case NSAPP_DATA2_RUNASSCRIPT: + ns_run_ascript (); + [self stop: self]; + return; #endif + case NSAPP_DATA2_RUNFILEDIALOG: + ns_run_file_dialog (); + [self stop: self]; + return; + } + } if (type == NSCursorUpdate && window == nil) { -- 2.39.2