- Added sendMessageNow:data:timeout: method to MMVimController - At end of live resize, send resize message with above method and if that fails fit window to text storage

git-svn-id: http://macvim.googlecode.com/svn/trunk@257 96c4425d-ca35-0410-94e5-3396d5c13a8f
This commit is contained in:
Bjorn Winckler
2007-09-22 14:24:37 +00:00
parent 140e41866a
commit 5341d45b06
5 changed files with 128 additions and 63 deletions
+1 -6
View File
@@ -742,13 +742,8 @@ static NSString *MMKeypadEnterString = @"KA";
- (void)viewDidEndLiveResize
{
// HACK! If a SetTextDimensionsMsgID message is lost while dragging to
// resize the window, then the text view and window sizes may become out of
// sync. To avoid this problem, resize the window when live resizes ends.
// This sometimes makes the window size 'jump' unpleasantly, but that is
// better than the alternative.
id windowController = [[self window] windowController];
[windowController resizeWindowToFit:self];
[windowController liveResizeDidEnd];
}
@end // MMTextView
+2
View File
@@ -51,6 +51,8 @@
- (void)dropFiles:(NSArray *)filenames;
- (void)dropString:(NSString *)string;
- (void)sendMessage:(int)msgid data:(NSData *)data;
- (BOOL)sendMessageNow:(int)msgid data:(NSData *)data
timeout:(NSTimeInterval)timeout;
@end
+27
View File
@@ -276,6 +276,33 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
}
}
- (BOOL)sendMessageNow:(int)msgid data:(NSData *)data
timeout:(NSTimeInterval)timeout
{
if (!isInitialized || inProcessCommandQueue)
return NO;
if (timeout < 0) timeout = 0;
BOOL sendOk = YES;
NSConnection *conn = [backendProxy connectionForProxy];
NSTimeInterval oldTimeout = [conn requestTimeout];
[conn setRequestTimeout:timeout];
@try {
[backendProxy processInput:msgid data:data];
}
@catch (NSException *e) {
sendOk = NO;
}
@finally {
[conn setRequestTimeout:oldTimeout];
}
return sendOk;
}
- (id)backendProxy
{
return backendProxy;
+1 -2
View File
@@ -58,12 +58,11 @@
- (void)showToolbar:(BOOL)on size:(int)size mode:(int)mode;
- (void)setMouseShape:(int)shape;
- (void)adjustLinespace:(int)linespace;
- (void)liveResizeDidEnd;
- (IBAction)addNewTab:(id)sender;
- (IBAction)toggleToolbar:(id)sender;
- (void)resizeWindowToFit:(id)sender;
@end
// vim: set ft=objc:
+97 -55
View File
@@ -50,6 +50,7 @@ enum {
- (NSSize)contentSizeForTextStorageSize:(NSSize)textViewSize;
- (NSRect)textViewRectForContentSize:(NSSize)contentSize;
- (NSSize)textStorageSizeForTextViewSize:(NSSize)textViewSize;
- (void)resizeWindowToFit:(id)sender;
- (NSRect)fitWindowToFrame:(NSRect)frame;
- (void)updateResizeIncrements;
- (NSTabViewItem *)addNewTabViewItem;
@@ -548,6 +549,50 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
}
}
- (void)liveResizeDidEnd
{
// TODO: Don't duplicate code from placeViews.
if (!setupDone) return;
// NOTE! It is assumed that the window has been resized so that it will
// exactly fit the text storage (possibly after resizing it). If this is
// not the case the display might be messed up.
BOOL resizeFailed = NO;
NSWindow *win = [self window];
NSRect contentRect = [win contentRectForFrameRect:[win frame]];
NSRect textViewRect = [self textViewRectForContentSize:contentRect.size];
NSSize tsSize = [self textStorageSizeForTextViewSize:textViewRect.size];
int dim[2], rows, cols;
[textStorage getMaxRows:&rows columns:&cols];
[textStorage fitToSize:tsSize rows:&dim[0] columns:&dim[1]];
if (dim[0] != rows || dim[1] != cols) {
NSData *data = [NSData dataWithBytes:dim length:2*sizeof(int)];
// NOTE: Since we're at the end of a live resize we want to make sure
// that the SetTextDimensionsMsgID message reaches Vim, else Vim and
// MacVim will have inconsistent states (i.e. the text view will be too
// large or too small for the window size). Thus, add a timeout (this
// may have to be tweaked) and take note if the message was sent or
// not.
resizeFailed = ![vimController sendMessageNow:SetTextDimensionsMsgID
data:data
timeout:.5];
}
[textView setFrame:textViewRect];
[self placeScrollbars];
if (resizeFailed) {
// Force the window size to match the text view size otherwise Vim and
// MacVim will have inconsistent states.
[self resizeWindowToFit:self];
}
}
- (IBAction)addNewTab:(id)sender
{
// NOTE! This can get called a lot if the user holds down the key
@@ -719,58 +764,6 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
return [self askBackendForStarRegister:pboard];
}
- (void)resizeWindowToFit:(id)sender
{
// NOTE: Be very careful when you call this method! Do not call while
// processing command queue, instead set 'shouldUpdateWindowSize' to YES.
// The only other place it is currently called is when live resize ends.
// This is done to ensure that the text view and window sizes match up
// (they may become out of sync if a SetTextDimensionsMsgID message to the
// backend is dropped).
if (!setupDone) return;
NSWindow *win = [self window];
NSRect frame = [win frame];
NSRect contentRect = [win contentRectForFrameRect:frame];
NSSize newSize = [self contentSizeForTextStorageSize:[textStorage size]];
// Keep top-left corner of the window fixed when resizing.
contentRect.origin.y -= newSize.height - contentRect.size.height;
contentRect.size = newSize;
frame = [win frameRectForContentRect:contentRect];
NSRect maxFrame = [win constrainFrameRect:frame toScreen:[win screen]];
// HACK! Assuming the window frame cannot already be placed too high,
// adjust 'maxFrame' so that it at least as high up as the current frame.
// The reason for doing this is that constrainFrameRect:toScreen: does not
// always seem to utilize as much area as possible.
if (NSMaxY(frame) > NSMaxY(maxFrame)) {
maxFrame.size.height = frame.origin.y - maxFrame.origin.y
+ frame.size.height;
}
if (!NSEqualRects(maxFrame, frame)) {
// The new window frame is too big to fit on the screen, so fit the
// text storage to the biggest frame which will fit on the screen.
//NSLog(@"Proposed window frame does not fit on the screen!");
frame = [self fitWindowToFrame:maxFrame];
}
//NSLog(@"%s %@", _cmd, NSStringFromRect(frame));
// HACK! If the window does resize, then windowDidResize is called which in
// turn calls placeViews. In case the computed new size of the window is
// no different from the current size, then we need to call placeViews
// manually.
if (NSEqualRects(frame, [win frame])) {
[self placeViews];
} else {
[win setFrame:frame display:YES];
}
}
@end // MMWindowController
@@ -840,6 +833,58 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
return size;
}
- (void)resizeWindowToFit:(id)sender
{
// NOTE: Be very careful when you call this method! Do not call while
// processing command queue, instead set 'shouldUpdateWindowSize' to YES.
// The only other place it is currently called is when live resize ends.
// This is done to ensure that the text view and window sizes match up
// (they may become out of sync if a SetTextDimensionsMsgID message to the
// backend is dropped).
if (!setupDone) return;
NSWindow *win = [self window];
NSRect frame = [win frame];
NSRect contentRect = [win contentRectForFrameRect:frame];
NSSize newSize = [self contentSizeForTextStorageSize:[textStorage size]];
// Keep top-left corner of the window fixed when resizing.
contentRect.origin.y -= newSize.height - contentRect.size.height;
contentRect.size = newSize;
frame = [win frameRectForContentRect:contentRect];
NSRect maxFrame = [win constrainFrameRect:frame toScreen:[win screen]];
// HACK! Assuming the window frame cannot already be placed too high,
// adjust 'maxFrame' so that it at least as high up as the current frame.
// The reason for doing this is that constrainFrameRect:toScreen: does not
// always seem to utilize as much area as possible.
if (NSMaxY(frame) > NSMaxY(maxFrame)) {
maxFrame.size.height = frame.origin.y - maxFrame.origin.y
+ frame.size.height;
}
if (!NSEqualRects(maxFrame, frame)) {
// The new window frame is too big to fit on the screen, so fit the
// text storage to the biggest frame which will fit on the screen.
//NSLog(@"Proposed window frame does not fit on the screen!");
frame = [self fitWindowToFrame:maxFrame];
}
//NSLog(@"%s %@", _cmd, NSStringFromRect(frame));
// HACK! If the window does resize, then windowDidResize is called which in
// turn calls placeViews. In case the computed new size of the window is
// no different from the current size, then we need to call placeViews
// manually.
if (NSEqualRects(frame, [win frame])) {
[self placeViews];
} else {
[win setFrame:frame display:YES];
}
}
- (NSRect)fitWindowToFrame:(NSRect)frame
{
if (!setupDone) return frame;
@@ -1108,9 +1153,6 @@ NSMutableArray *buildMenuAddress(NSMenu *menu)
// dim[0], dim[1]);
NSData *data = [NSData dataWithBytes:dim length:2*sizeof(int)];
// NOTE! This can get called a lot when in live resize, which causes
// the connection buffers to fill up. If we wait for the message to be
// sent then the app might become unresponsive.
[vimController sendMessage:SetTextDimensionsMsgID data:data];
}