From: Adrian Robert Date: Sat, 7 Feb 2009 11:04:22 +0000 (+0000) Subject: * nsterm.m (EmacsApp-sendEvent:): Defer NSApplicationDefined event X-Git-Tag: emacs-pretest-23.0.91~363 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=3175b12ae7dc142799e993a3bc5e076d47e20bd4;p=emacs.git * nsterm.m (EmacsApp-sendEvent:): Defer NSApplicationDefined event when modal window is active. (Bug #2152) (applicationShouldTerminate:): Remove now-unneeded while loop around NSRunAlertPanel. * nsmenu.m (popupSession): New file-global variable. (pop_down_menu): End the popupSession before closing dialog. (ns_popup_dialog): BLOCK_INPUT around dialog presentation. (EmacsDialogPanel-runDialogAt:): Don't place window (superfluous), don't query NSApp for events (just sleep instead). --- diff --git a/src/ChangeLog b/src/ChangeLog index 67ef7ad46a5..280af6c8b42 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2009-02-07 Adrian Robert + + * nsterm.m (EmacsApp-sendEvent:): Defer NSApplicationDefined event + when modal window is active. (Bug #2152) + (applicationShouldTerminate:): Remove now-unneeded while loop + around NSRunAlertPanel. + + * nsmenu.m (popupSession): New file-global variable. + (pop_down_menu): End the popupSession before closing dialog. + (ns_popup_dialog): BLOCK_INPUT around dialog presentation. + (EmacsDialogPanel-runDialogAt:): Don't place window (superfluous), + don't query NSApp for events (just sleep instead). + 2009-02-07 Eli Zaretskii * coding.c (syms_of_coding) : Modify diff --git a/src/nsmenu.m b/src/nsmenu.m index c6d4c21a179..f6b2075a841 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -73,6 +73,7 @@ EmacsMenu *mainMenu, *svcsMenu, *dockMenu; /* Nonzero means a menu is currently active. */ static int popup_activated_flag; +static NSModalSession popupSession; /* NOTE: toolbar implementation is at end, following complete menu implementation. */ @@ -1495,6 +1496,7 @@ pop_down_menu (Lisp_Object arg) struct Lisp_Save_Value *p = XSAVE_VALUE (arg); popup_activated_flag = 0; BLOCK_INPUT; + [NSApp endModalSession: popupSession]; [((EmacsDialogPanel *) (p->pointer)) close]; [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; UNBLOCK_INPUT; @@ -1554,6 +1556,8 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) p.x = (int)f->left_pos + ((int)FRAME_COLUMN_WIDTH (f) * f->text_cols)/2; p.y = (int)f->top_pos + (FRAME_LINE_HEIGHT (f) * f->text_lines)/2; + + BLOCK_INPUT; dialog = [[EmacsDialogPanel alloc] initFromContents: contents isQuestion: isQ]; { @@ -1567,6 +1571,7 @@ ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) [dialog close]; [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; + UNBLOCK_INPUT; return tem; } @@ -1872,27 +1877,21 @@ void process_dialog (id window, Lisp_Object list) - (Lisp_Object)runDialogAt: (NSPoint)p { - NSEvent *e; - NSModalSession session; int ret; - [self center]; /*XXX p ignored? */ - [self orderFront: NSApp]; - - session = [NSApp beginModalSessionForWindow: self]; + popupSession = [NSApp beginModalSessionForWindow: self]; while (popup_activated_flag - && (ret = [NSApp runModalSession: session]) == NSRunContinuesResponse) + && (ret = [NSApp runModalSession: popupSession]) + == NSRunContinuesResponse) { - timer_check (1); // for timers.el, indep of atimers; might not return - e = [NSApp nextEventMatchingMask: NSAnyEventMask - untilDate: [NSDate dateWithTimeIntervalSinceNow: 1] - inMode: NSModalPanelRunLoopMode - dequeue: NO]; -/*fprintf (stderr, "ret = %d\te = %p\n", ret, e);*/ + /* Run this for timers.el, indep of atimers; might not return. + TODO: use return value to avoid calling every iteration. */ + timer_check (1); + [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]]; } - [NSApp endModalSession: session]; + [NSApp endModalSession: popupSession]; - { // FIXME: BIG UGLY HACK!!! + { /* FIXME: BIG UGLY HACK!!! */ Lisp_Object tmp; *(EMACS_INT*)(&tmp) = ret; return tmp; diff --git a/src/nsterm.m b/src/nsterm.m index 2ef3a3ec906..b674edae580 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -4037,7 +4037,8 @@ ns_term_shutdown (int sig) - (void)sendEvent: (NSEvent *)theEvent /* -------------------------------------------------------------------------- - Events posted by ns_send_appdefined interrupt the run loop here + Called when NSApp is running for each event received. Used to stop + the loop when we choose, since there's no way to just run one iteration. -------------------------------------------------------------------------- */ { int type = [theEvent type]; @@ -4081,8 +4082,19 @@ ns_term_shutdown (int sig) if (type == NSApplicationDefined) { - last_appdefined_event = theEvent; - [self stop: self]; + /* Events posted by ns_send_appdefined interrupt the run loop here. + But, if a modal window is up, an appdefined can still come through, + (e.g., from a makeKeyWindow event) but stopping self also stops the + modal loop. Just defer it until later. */ + if ([NSApp modalWindow] == nil) + { + last_appdefined_event = theEvent; + [self stop: self]; + } + else + { + send_appdefined = YES; + } } [super sendEvent: theEvent]; @@ -4199,28 +4211,15 @@ ns_term_shutdown (int sig) if (ns_shutdown_properly || NILP (ns_confirm_quit)) return NSTerminateNow; - /* XXX: This while() loop is needed because if the user switches to another - application while the panel is up, it is taken down w/a return value - of NSRunStoppedResponse, and the event queue gets messed up. - In this case resend the appdefined and put up the window again. */ - while (1) { ret = NSRunAlertPanel([[NSProcessInfo processInfo] processName], [NSString stringWithUTF8String:"Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?"], @"Save Buffers and Exit", @"Cancel", nil); if (ret == NSAlertDefaultReturn) - { - send_appdefined = YES; - ns_send_appdefined(-1); return NSTerminateNow; - } else if (ret == NSAlertAlternateReturn) - { - send_appdefined = YES; - ns_send_appdefined(-1); return NSTerminateCancel; - } - } + return NSTerminateNow; /* just in case */ }