From b9e21b1638c1c974351a7f1fe3304b4c675780bb Mon Sep 17 00:00:00 2001 From: Bjorn Winckler Date: Sat, 2 Aug 2008 19:47:35 +0200 Subject: [PATCH] Modify how and when preloaded windows open This hopefully fixes the bug where a preloaded window sometimes failed to ever show up but MacVim would still think that it was showing. --- src/MacVim/MMAppController.m | 7 ++++++ src/MacVim/MMBackend.h | 2 +- src/MacVim/MMBackend.m | 15 ++++++++----- src/MacVim/MMVimController.h | 3 +++ src/MacVim/MMVimController.m | 19 ++++++++++++++-- src/MacVim/MMWindowController.h | 1 + src/MacVim/MMWindowController.m | 13 ++++++++++- src/MacVim/MacVim.h | 2 +- src/MacVim/MacVim.m | 2 +- src/MacVim/gui_macvim.m | 13 +++-------- src/main.c | 50 ++++++++++++++++++++++------------------- 11 files changed, 83 insertions(+), 44 deletions(-) diff --git a/src/MacVim/MMAppController.m b/src/MacVim/MMAppController.m index d28984d2..054a1a60 100644 --- a/src/MacVim/MMAppController.m +++ b/src/MacVim/MMAppController.m @@ -944,6 +944,7 @@ static int executeInLoginShell(NSString *path, NSArray *args); // This backend was preloaded, so add it to the cache and schedule // another vim process to be preloaded. preloadPid = -1; + [vc setIsPreloading:YES]; [cachedVimControllers addObject:vc]; [self scheduleVimControllerPreloadAfterDelay:1]; return vc; @@ -1423,6 +1424,12 @@ static int executeInLoginShell(NSString *path, NSArray *args); MMVimController *vc = [cachedVimControllers objectAtIndex:0]; [vimControllers addObject:vc]; [cachedVimControllers removeObjectAtIndex:0]; + [vc setIsPreloading:NO]; + + // If the Vim process has finished loading then the window will displayed + // now, otherwise it will be displayed when the OpenWindowMsgID message is + // received. + [[vc windowController] showWindow]; // Since we've taken one controller from the cache we take the opportunity // to preload another. diff --git a/src/MacVim/MMBackend.h b/src/MacVim/MMBackend.h index 66ea66fe..96dafd26 100644 --- a/src/MacVim/MMBackend.h +++ b/src/MacVim/MMBackend.h @@ -63,7 +63,7 @@ - (void)queueMessage:(int)msgid properties:(NSDictionary *)props; - (BOOL)checkin; -- (BOOL)openVimWindow; +- (BOOL)openGUIWindow; - (void)clearAll; - (void)clearBlockFromRow:(int)row1 column:(int)col1 toRow:(int)row2 column:(int)col2; diff --git a/src/MacVim/MMBackend.m b/src/MacVim/MMBackend.m index 4418bbf2..b336b165 100644 --- a/src/MacVim/MMBackend.m +++ b/src/MacVim/MMBackend.m @@ -255,7 +255,9 @@ static NSString *MMSymlinkWarningString = // MacVim to be opened. We probably got here as a result of the // user quitting MacVim while the process was preloading, so exit // this process too. - mch_exit(0); + // (Don't use mch_exit() since it assumes the process has properly + // started.) + exit(0); } NSBundle *mainBundle = [NSBundle mainBundle]; @@ -352,9 +354,9 @@ static NSString *MMSymlinkWarningString = return ok; } -- (BOOL)openVimWindow +- (BOOL)openGUIWindow { - [self queueMessage:OpenVimWindowMsgID data:nil]; + [self queueMessage:OpenWindowMsgID data:nil]; return YES; } @@ -565,6 +567,10 @@ static NSString *MMSymlinkWarningString = - (void)exit { + // NOTE: This is called if mch_exit() is called. Since we assume here that + // the process has started properly, be sure to use exit() instead of + // mch_exit() to prematurely terminate a process. + // To notify MacVim that this Vim process is exiting we could simply // invalidate the connection and it would automatically receive a // connectionDidDie: notification. However, this notification seems to @@ -1541,7 +1547,6 @@ static NSString *MMSymlinkWarningString = } [self processInputQueue]; - [self openVimWindow]; } - (oneway void)acknowledgeConnection @@ -2272,7 +2277,7 @@ static NSString *MMSymlinkWarningString = if (ga_grow(&global_alist.al_ga, 1) == FAIL || (p = [fname vimStringSave]) == NULL) - mch_exit(2); + exit(2); // See comment in -[MMBackend exit] else alist_add(&global_alist, p, 2); } diff --git a/src/MacVim/MMVimController.h b/src/MacVim/MMVimController.h index a31df15e..04755d4f 100644 --- a/src/MacVim/MMVimController.h +++ b/src/MacVim/MMVimController.h @@ -38,6 +38,7 @@ #ifdef MM_ENABLE_PLUGINS MMPlugInInstanceMediator *instanceMediator; #endif + BOOL isPreloading; } - (id)initWithBackend:(id)backend pid:(int)processIdentifier; @@ -48,6 +49,8 @@ - (MMWindowController *)windowController; - (NSDictionary *)vimState; - (NSMenu *)mainMenu; +- (BOOL)isPreloading; +- (void)setIsPreloading:(BOOL)yn; - (void)cleanup; - (void)dropFiles:(NSArray *)filenames forceOpen:(BOOL)force; - (void)dropString:(NSString *)string; diff --git a/src/MacVim/MMVimController.m b/src/MacVim/MMVimController.m index 9cb7797e..2f13fb29 100644 --- a/src/MacVim/MMVimController.m +++ b/src/MacVim/MMVimController.m @@ -200,6 +200,16 @@ static BOOL isUnsafeMessage(int msgid); return mainMenu; } +- (BOOL)isPreloading +{ + return isPreloading; +} + +- (void)setIsPreloading:(BOOL)yn +{ + isPreloading = yn; +} + - (void)setServerName:(NSString *)name { if (name != serverName) { @@ -660,8 +670,13 @@ static BOOL isUnsafeMessage(int msgid); // msgid != EnableMenuItemMsgID) // NSLog(@"%@ %s%s", [self className], _cmd, MessageStrings[msgid]); - if (OpenVimWindowMsgID == msgid) { + if (OpenWindowMsgID == msgid) { [windowController openWindow]; + + // If the vim controller is preloading then the window will be + // displayed when it is taken off the preload cache. + if (!isPreloading) + [windowController showWindow]; } else if (BatchDrawMsgID == msgid) { [[[windowController vimView] textView] performBatchDrawWithData:data]; } else if (SelectTabMsgID == msgid) { @@ -1419,7 +1434,7 @@ isUnsafeMessage(int msgid) // example, UpdateTabBarMsgID may delete NSTabViewItem objects so it goes // on this list. static int unsafeMessages[] = { // REASON MESSAGE IS ON THIS LIST: - OpenVimWindowMsgID, // Changes lots of state + //OpenWindowMsgID, // Changes lots of state UpdateTabBarMsgID, // May delete NSTabViewItem RemoveMenuItemMsgID, // Deletes NSMenuItem DestroyScrollbarMsgID, // Deletes NSScroller diff --git a/src/MacVim/MMWindowController.h b/src/MacVim/MMWindowController.h index 31fa81dc..55dec0f7 100644 --- a/src/MacVim/MMWindowController.h +++ b/src/MacVim/MMWindowController.h @@ -36,6 +36,7 @@ - (void)setWindowAutosaveKey:(NSString *)key; - (void)cleanup; - (void)openWindow; +- (void)showWindow; - (void)updateTabsWithData:(NSData *)data; - (void)selectTabWithIndex:(int)idx; - (void)setTextDimensionsWithRows:(int)rows columns:(int)cols live:(BOOL)live; diff --git a/src/MacVim/MMWindowController.m b/src/MacVim/MMWindowController.m index ec45ee72..1b44a5d7 100644 --- a/src/MacVim/MMWindowController.m +++ b/src/MacVim/MMWindowController.m @@ -262,7 +262,8 @@ - (void)openWindow { - [[MMAppController sharedInstance] windowControllerWillOpen:self]; + // Indicates that the window is ready to be displayed, but do not display + // (or place) it yet -- that is done in showWindow. [self addNewTabViewItem]; @@ -270,6 +271,16 @@ [self updateResizeConstraints]; [self resizeWindowToFitContentSize:[vimView desiredSize]]; +} + +- (void)showWindow +{ + // Actually show the window on screen. However, if openWindow hasn't + // already been called nothing will happen (the window will be displayed + // later). + if (!setupDone) return; + + [[MMAppController sharedInstance] windowControllerWillOpen:self]; [[self window] makeKeyAndOrderFront:self]; } diff --git a/src/MacVim/MacVim.h b/src/MacVim/MacVim.h index 85889189..09891963 100644 --- a/src/MacVim/MacVim.h +++ b/src/MacVim/MacVim.h @@ -109,7 +109,7 @@ extern char *MessageStrings[]; enum { - OpenVimWindowMsgID = 1, + OpenWindowMsgID = 1, InsertTextMsgID, KeyDownMsgID, CmdKeyMsgID, diff --git a/src/MacVim/MacVim.m b/src/MacVim/MacVim.m index c3450508..6dda85da 100644 --- a/src/MacVim/MacVim.m +++ b/src/MacVim/MacVim.m @@ -16,7 +16,7 @@ char *MessageStrings[] = { "INVALID MESSAGE ID", - "OpenVimWindowMsgID", + "OpenWindowMsgID", "InsertTextMsgID", "KeyDownMsgID", "CmdKeyMsgID", diff --git a/src/MacVim/gui_macvim.m b/src/MacVim/gui_macvim.m index 74b8b7bb..325dd531 100644 --- a/src/MacVim/gui_macvim.m +++ b/src/MacVim/gui_macvim.m @@ -150,16 +150,7 @@ gui_mch_exit(int rc) int gui_mch_open(void) { - // For preloaded Vim processes we delay opening the GUI window until - // gui_macvim_wait_for_startup() is called. (If for some reason preloading - // didn't work as expected, the "normal" behavior can be restored by - // disabling preloading.) - - MMBackend *backend = [MMBackend sharedInstance]; - if ([backend waitForAck]) - return OK; - - return [backend openVimWindow]; + return [[MMBackend sharedInstance] openGUIWindow]; } @@ -1655,6 +1646,8 @@ void gui_macvim_get_window_layout(int *count, int *layout) { if (!(count && layout)) return; + // NOTE: Only set 'layout' if the backend has requested a != 0 layout, else + // any command line arguments (-p/-o) would be ignored. int window_layout = [[MMBackend sharedInstance] initialWindowLayout]; if (window_layout > 0 && window_layout < 4) { // The window_layout numbers must match the WIN_* defines in main.c. diff --git a/src/main.c b/src/main.c index e871e120..091de210 100644 --- a/src/main.c +++ b/src/main.c @@ -751,29 +751,6 @@ main newline_on_exit = TRUE; #endif -#ifdef FEAT_GUI_MACVIM - /* We want to delay calling this function for as long as possible, since it - * will result in faster startup for cached processes. However, we must - * react before wait_return() otherwise no window is visible before a - * "hit ENTER" message is displayed. */ - gui_macvim_wait_for_startup(); - gui_macvim_get_window_layout(¶ms.window_count, ¶ms.window_layout); - -# ifdef MAC_CLIENTSERVER - // NOTE: Can't set server name at same time as WIN32 because gui.in_use - // isn't set then. Servers are only supported in GUI mode. - // Also, in case the above call blocks this process another Vim process may - // open in the meantime. If it did then it could be named e.g. VIM3 - // whereas this may be VIM2, which looks weird. - if (params.servername != NULL && gui.in_use) - { - serverRegisterName(params.servername); - vim_free(params.servername); - params.servername = NULL; - } -# endif -#endif - /* * When done something that is not allowed or error message call * wait_return. This must be done before starttermcap(), because it may @@ -826,6 +803,33 @@ main no_wait_return = TRUE; +#ifdef FEAT_GUI_MACVIM + /* We want to delay calling this function for as long as possible, since it + * will result in faster startup for cached processes. However, we react + * before create_windows() so that we can open files by adding to the + * arglist. */ + gui_macvim_wait_for_startup(); + + /* Since MacVim may receive the list of files to open via an Apple event + * (as opposed to from the command line) we must manually check to see if + * the window layout should be changed. */ + gui_macvim_get_window_layout(¶ms.window_count, ¶ms.window_layout); + +# ifdef MAC_CLIENTSERVER + // NOTE: Can't set server name at same time as WIN32 because gui.in_use + // isn't set then. Servers are only supported in GUI mode. + // Also, in case the above call blocks this process another Vim process may + // open in the meantime. If it did then it could be named e.g. VIM3 + // whereas this may be VIM2, which looks weird. + if (params.servername != NULL && gui.in_use) + { + serverRegisterName(params.servername); + vim_free(params.servername); + params.servername = NULL; + } +# endif +#endif + /* * Create the requested number of windows and edit buffers in them. * Also does recovery if "recoverymode" set. -- 2.11.4.GIT