mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-07 15:37:14 +02:00
Dialog box handling updated
Keep waiting for dialog reply until it is received. Any input received during this wait is discarded unless it is a 'set text dimensions' message (or keyboard/mouse input). Also, make setDialogReturn: a synchronous call so that it is less likely to get dropped.
This commit is contained in:
+54
-7
@@ -80,6 +80,7 @@ static NSString *MMSymlinkWarningString =
|
||||
|
||||
|
||||
@interface MMBackend (Private)
|
||||
- (void)waitForDialogReturn;
|
||||
- (void)queueVimStateMessage;
|
||||
- (void)processInputQueue;
|
||||
- (void)handleInputEvent:(int)msgid data:(NSData *)data;
|
||||
@@ -640,9 +641,7 @@ static NSString *MMSymlinkWarningString =
|
||||
@try {
|
||||
[frontendProxy showSavePanelForDirectory:ds title:ts saving:saving];
|
||||
|
||||
// Wait until a reply is sent from MMVimController.
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
|
||||
beforeDate:[NSDate distantFuture]];
|
||||
[self waitForDialogReturn];
|
||||
|
||||
if (dialogReturn && [dialogReturn isKindOfClass:[NSString class]]) {
|
||||
char_u *ret = (char_u*)[dialogReturn UTF8String];
|
||||
@@ -664,13 +663,18 @@ static NSString *MMSymlinkWarningString =
|
||||
return (char *)s;
|
||||
}
|
||||
|
||||
- (oneway void)setDialogReturn:(in bycopy id)obj
|
||||
- (void)setDialogReturn:(in bycopy id)obj
|
||||
{
|
||||
// NOTE: This is called by
|
||||
// - [MMVimController panelDidEnd:::], and
|
||||
// - [MMVimController alertDidEnd:::],
|
||||
// to indicate that a save/open panel or alert has finished.
|
||||
|
||||
// We want to distinguish between "no dialog return yet" and "dialog
|
||||
// returned nothing". The former can be tested with dialogReturn == nil,
|
||||
// the latter with dialogReturn == [NSNull null].
|
||||
if (!obj) obj = [NSNull null];
|
||||
|
||||
if (obj != dialogReturn) {
|
||||
[dialogReturn release];
|
||||
dialogReturn = [obj retain];
|
||||
@@ -719,9 +723,7 @@ static NSString *MMSymlinkWarningString =
|
||||
informativeText:text buttonTitles:buttons
|
||||
textFieldString:textFieldString];
|
||||
|
||||
// Wait until a reply is sent from MMVimController.
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
|
||||
beforeDate:[NSDate distantFuture]];
|
||||
[self waitForDialogReturn];
|
||||
|
||||
if (dialogReturn && [dialogReturn isKindOfClass:[NSArray class]]
|
||||
&& [dialogReturn count]) {
|
||||
@@ -1475,6 +1477,49 @@ static NSString *MMSymlinkWarningString =
|
||||
|
||||
@implementation MMBackend (Private)
|
||||
|
||||
- (void)waitForDialogReturn
|
||||
{
|
||||
// Keep processing the run loop until a dialog returns. To avoid getting
|
||||
// stuck in an endless loop (could happen if the setDialogReturn: message
|
||||
// was lost) we also do some paranoia checks.
|
||||
//
|
||||
// Note that in Cocoa the user can still resize windows and select menu
|
||||
// items while a sheet is being displayed, so we can't just wait for the
|
||||
// first message to arrive and assume that is the setDialogReturn: call.
|
||||
|
||||
while (nil == dialogReturn && !got_int && [connection isValid]
|
||||
&& !isTerminating)
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
|
||||
beforeDate:[NSDate distantFuture]];
|
||||
|
||||
// Search for any resize messages on the input queue. All other messages
|
||||
// on the input queue are dropped. The reason why we single out resize
|
||||
// messages is because the user may have resized the window while a sheet
|
||||
// was open.
|
||||
int i, count = [inputQueue count];
|
||||
if (count > 0) {
|
||||
id textDimData = nil;
|
||||
if (count%2 == 0) {
|
||||
for (i = count-2; i >= 0; i -= 2) {
|
||||
int msgid = [[inputQueue objectAtIndex:i] intValue];
|
||||
if (SetTextDimensionsMsgID == msgid) {
|
||||
textDimData = [[inputQueue objectAtIndex:i+1] retain];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[inputQueue removeAllObjects];
|
||||
|
||||
if (textDimData) {
|
||||
[inputQueue addObject:
|
||||
[NSNumber numberWithInt:SetTextDimensionsMsgID]];
|
||||
[inputQueue addObject:textDimData];
|
||||
[textDimData release];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)queueVimStateMessage
|
||||
{
|
||||
// NOTE: This is the place to add Vim state that needs to be accessed from
|
||||
@@ -1494,6 +1539,8 @@ static NSString *MMSymlinkWarningString =
|
||||
|
||||
- (void)processInputQueue
|
||||
{
|
||||
if ([inputQueue count] == 0) return;
|
||||
|
||||
// NOTE: One of the input events may cause this method to be called
|
||||
// recursively, so copy the input queue to a local variable and clear it
|
||||
// before starting to process input events (otherwise we could get stuck in
|
||||
|
||||
@@ -47,6 +47,8 @@ static NSTimeInterval MMBackendProxyRequestTimeout = 0;
|
||||
static NSTimeInterval MMResendInterval = 0.5;
|
||||
#endif
|
||||
|
||||
static NSTimeInterval MMSetDialogReturnTimeout = 1.0;
|
||||
|
||||
|
||||
@interface MMAlert : NSAlert {
|
||||
NSTextField *textField;
|
||||
@@ -813,6 +815,15 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
context:(void *)context
|
||||
{
|
||||
NSString *path = (code == NSOKButton) ? [panel filename] : nil;
|
||||
|
||||
// NOTE! setDialogReturn: is a synchronous call so set a proper timeout to
|
||||
// avoid waiting forever for it to finish. We make this a synchronous call
|
||||
// so that we can be fairly certain that Vim doesn't think the dialog box
|
||||
// is still showing when MacVim has in fact already dismissed it.
|
||||
NSConnection *conn = [backendProxy connectionForProxy];
|
||||
NSTimeInterval oldTimeout = [conn requestTimeout];
|
||||
[conn setRequestTimeout:MMSetDialogReturnTimeout];
|
||||
|
||||
@try {
|
||||
[backendProxy setDialogReturn:path];
|
||||
|
||||
@@ -825,6 +836,9 @@ static NSTimeInterval MMResendInterval = 0.5;
|
||||
@catch (NSException *e) {
|
||||
NSLog(@"Exception caught in %s %@", _cmd, e);
|
||||
}
|
||||
@finally {
|
||||
[conn setRequestTimeout:oldTimeout];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)alertDidEnd:(MMAlert *)alert code:(int)code context:(void *)context
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
@protocol MMBackendProtocol
|
||||
- (oneway void)processInput:(int)msgid data:(in bycopy NSData *)data;
|
||||
- (oneway void)processInputAndData:(in bycopy NSArray *)messages;
|
||||
- (oneway void)setDialogReturn:(in bycopy id)obj;
|
||||
- (void)setDialogReturn:(in bycopy id)obj;
|
||||
- (NSString *)evaluateExpression:(in bycopy NSString *)expr;
|
||||
- (BOOL)starRegisterToPasteboard:(byref NSPasteboard *)pboard;
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user