From e365162bbb79835af5d92a30cd7d434f14726b4a Mon Sep 17 00:00:00 2001 From: "bjorn.winckler" Date: Thu, 16 Aug 2007 08:56:10 +0000 Subject: [PATCH] - Fixed bug where tab bar controller never removed itself as an observer - Shutdown changed; when connection dies, cleanup is called where all delegates, notifications etc. are reset. - Views are now initialized in the designated initializer of MMWindowController instead of in the nib. For some reason some object in the nib got deallocated more than once and this caused EXC_BAD_ACCESS errors. Hopefully this bug is now fixed. - Put @try/@catch clause around processInput:data: DO call since this can throw an exception if the underlying port is dead. - GUI status line is no longer used. - Added description methods to MMWindowController and MMVimController. git-svn-id: http://macvim.googlecode.com/svn/trunk@144 96c4425d-ca35-0410-94e5-3396d5c13a8f --- MMAppController.m | 2 + MMBackend.m | 3 + MMVimController.h | 3 +- MMVimController.m | 86 ++++++++++++++--- MMWindowController.h | 5 + MMWindowController.m | 256 +++++++++++++++++++++++++++++++++------------------ 6 files changed, 248 insertions(+), 107 deletions(-) diff --git a/MMAppController.m b/MMAppController.m index df3356be..78a4a342 100644 --- a/MMAppController.m +++ b/MMAppController.m @@ -220,6 +220,8 @@ - (void)removeVimController:(id)controller { + [[controller windowController] close]; + [vimControllers removeObject:controller]; if (![vimControllers count]) { diff --git a/MMBackend.m b/MMBackend.m index 71d5edc0..7499695b 100644 --- a/MMBackend.m +++ b/MMBackend.m @@ -57,6 +57,8 @@ static int specialKeyToNSKey(int key); - (void)dealloc { + //NSLog(@"%@ %s", [self className], _cmd); + [[NSNotificationCenter defaultCenter] removeObserver:self]; [queue release]; @@ -295,6 +297,7 @@ static int specialKeyToNSKey(int key); // By invalidating the NSConnection the MMWindowController immediately // finds out that the connection is down and as a result // [MMWindowController connectionDidDie:] is invoked. + //NSLog(@"%@ %s", [self className], _cmd); [[NSNotificationCenter defaultCenter] removeObserver:self]; [connection invalidate]; } diff --git a/MMVimController.h b/MMVimController.h index 7024e04c..2efdbc39 100644 --- a/MMVimController.h +++ b/MMVimController.h @@ -18,6 +18,7 @@ @interface MMVimController : NSObject { + BOOL isInitialized; MMWindowController *windowController; id backendProxy; BOOL inProcessCommandQueue; @@ -32,7 +33,7 @@ - (id)initWithBackend:(id)backend; - (id)backendProxy; - (MMWindowController *)windowController; -- (void)windowWillClose:(NSNotification *)notification; +- (void)cleanup; - (void)sendMessage:(int)msgid data:(NSData *)data wait:(BOOL)wait; @end diff --git a/MMVimController.m b/MMVimController.m index 99e48fda..718b1934 100644 --- a/MMVimController.m +++ b/MMVimController.m @@ -93,6 +93,23 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(connectionDidDie:) name:NSConnectionDidDieNotification object:connection]; + + NSWindow *win = [windowController window]; + +#if 0 + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(windowWillClose:) + name:NSWindowWillCloseNotification + object:win]; +#endif + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(windowDidBecomeMain:) + name:NSWindowDidBecomeMainNotification + object:win]; + + isInitialized = YES; } return self; @@ -101,17 +118,16 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag) - (void)dealloc { //NSLog(@"%@ %s", [self className], _cmd); + isInitialized = NO; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - [backendProxy release]; - [sendQueue release]; + [backendProxy release]; backendProxy = nil; + [sendQueue release]; sendQueue = nil; - [toolbarItemDict release]; - [toolbar release]; - [popupMenuItems release]; - [mainMenuItems release]; - [windowController release]; + [toolbarItemDict release]; toolbarItemDict = nil; + [toolbar release]; toolbar = nil; + [popupMenuItems release]; popupMenuItems = nil; + [mainMenuItems release]; mainMenuItems = nil; + [windowController release]; windowController = nil; [super dealloc]; } @@ -123,6 +139,8 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag) - (void)sendMessage:(int)msgid data:(NSData *)data wait:(BOOL)wait { + if (!isInitialized) return; + if (inProcessCommandQueue) { //NSLog(@"In process command queue; delaying message send."); [sendQueue addObject:[NSNumber numberWithInt:msgid]]; @@ -134,7 +152,13 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag) } if (wait) { - [backendProxy processInput:msgid data:data]; + @try { + [backendProxy processInput:msgid data:data]; + } + @catch (NSException *e) { + NSLog(@"%@ %s Exception caught during DO call: %@", + [self className], _cmd, e); + } } else { // Do not wait for the message to be sent, i.e. drop the message if it // can't be delivered immediately. @@ -161,10 +185,23 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag) return backendProxy; } +- (void)cleanup +{ + //NSLog(@"%@ %s", [self className], _cmd); + if (!isInitialized) return; + + isInitialized = NO; + [toolbar setDelegate:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [windowController cleanup]; +} + - (oneway void)showSavePanelForDirectory:(in bycopy NSString *)dir title:(in bycopy NSString *)title saving:(int)saving { + if (!isInitialized) return; + [windowController setStatusText:title]; if (saving) { @@ -186,6 +223,8 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag) - (oneway void)processCommandQueue:(in NSArray *)queue { + if (!isInitialized) return; + unsigned i, count = [queue count]; if (count % 2) { NSLog(@"WARNING: Uneven number of components (%d) in flush queue " @@ -239,17 +278,24 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag) } } +#if 0 - (void)windowWillClose:(NSNotification *)notification { + NSLog(@"%@ %s%@", [self className], _cmd, notification); + + //[self cleanup]; + // NOTE! This causes the call to removeVimController: to be delayed. [[NSApp delegate] performSelectorOnMainThread:@selector(removeVimController:) withObject:self waitUntilDone:NO]; } +#endif - (void)windowDidBecomeMain:(NSNotification *)notification { - [self updateMainMenu]; + if (isInitialized) + [self updateMainMenu]; } - (NSToolbarItem *)toolbar:(NSToolbar *)theToolbar @@ -839,6 +885,7 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag) - (void)updateMainMenu { +#if 1 NSMenu *mainMenu = [NSApp mainMenu]; // Stop NSApp from updating the Window menu. @@ -873,6 +920,7 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag) [NSApp setWindowsMenu:windowMenu]; } +#endif shouldUpdateMainMenu = NO; } @@ -964,9 +1012,14 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag) - (void)connectionDidDie:(NSNotification *)notification { - //NSLog(@"A MMVimController lost its connection to the backend; " - // "closing the controller."); - [windowController close]; + //NSLog(@"%@ %s%@", [self className], _cmd, notification); + + [self cleanup]; + + // NOTE! This causes the call to removeVimController: to be delayed. + [[NSApp delegate] + performSelectorOnMainThread:@selector(removeVimController:) + withObject:self waitUntilDone:NO]; } - (BOOL)executeActionWithName:(NSString *)name @@ -1004,6 +1057,11 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag) return NO; } +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ : isInitialized=%d inProcessCommandQueue=%d mainMenuItems=%@ popupMenuItems=%@ toolbar=%@", [self className], isInitialized, inProcessCommandQueue, mainMenuItems, popupMenuItems, toolbar]; +} + @end // MMVimController (Private) diff --git a/MMWindowController.h b/MMWindowController.h index 5227c032..8024334d 100644 --- a/MMWindowController.h +++ b/MMWindowController.h @@ -10,6 +10,10 @@ #import + +#define MM_USE_EMPTY_WINDOW 1 + + @class PSMTabBarControl; @class MMTextView; @class MMTextStorage; @@ -40,6 +44,7 @@ - (MMTextStorage *)textStorage; - (NSString *)windowAutosaveKey; - (void)setWindowAutosaveKey:(NSString *)key; +- (void)cleanup; - (void)openWindow; - (void)updateTabsWithData:(NSData *)data; - (void)selectTabWithIndex:(int)idx; diff --git a/MMWindowController.m b/MMWindowController.m index 7cd9e936..dcb0a94d 100644 --- a/MMWindowController.m +++ b/MMWindowController.m @@ -98,7 +98,12 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) - (id)initWithVimController:(MMVimController *)controller { - if ((self = [super initWithWindowNibName:@"VimWindow"])) { +#if MM_USE_EMPTY_WINDOW + if ((self = [super initWithWindowNibName:@"EmptyWindow"])) +#else + if ((self = [super initWithWindowNibName:@"VimWindow"])) +#endif + { vimController = controller; scrollbars = [[NSMutableArray alloc] init]; @@ -130,7 +135,8 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) [textStorage addLayoutManager:lm]; [lm addTextContainer:tc]; - textView = [[MMTextView alloc] initWithFrame:NSZeroRect + NSView *contentView = [[self window] contentView]; + textView = [[MMTextView alloc] initWithFrame:[contentView frame] textContainer:tc]; NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; @@ -138,10 +144,57 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) int top = [ud integerForKey:MMTextInsetTopKey]; [textView setTextContainerInset:NSMakeSize(left, top)]; + [contentView addSubview:textView]; + // The text storage retains the layout manager which in turn retains // the text container. [tc release]; [lm release]; + +#if MM_USE_EMPTY_WINDOW + // Create the tabline separator (which may be visible when the tabline + // is hidden). + NSRect tabSepRect = [contentView frame]; + tabSepRect.origin.y = NSMaxY(tabSepRect)-1; + tabSepRect.size.height = 1; + tablineSeparator = [[NSBox alloc] initWithFrame:tabSepRect]; + + // Create the tab view (which is never visible, but the tab bar control + // needs it to function). + tabView = [[NSTabView alloc] initWithFrame:NSZeroRect]; + + // Create the tab bar control (which is responsible for actually + // drawing the tabline and tabs). + NSRect tabFrame = [contentView frame]; + tabFrame.origin.y = NSMaxY(tabFrame) - 22; + tabFrame.size.height = 22; + tabBarControl = [[PSMTabBarControl alloc] initWithFrame:tabFrame]; + + [tabView setDelegate:tabBarControl]; + + [tabBarControl setTabView:tabView]; + [tabBarControl setDelegate:self]; + [tabBarControl setHidden:YES]; + [tabBarControl setAutoresizingMask:NSViewWidthSizable|NSViewMinYMargin]; + [tabBarControl setCellMinWidth:[ud integerForKey:MMTabMinWidthKey]]; + [tabBarControl setCellMaxWidth:[ud integerForKey:MMTabMaxWidthKey]]; + [tabBarControl setCellOptimumWidth: + [ud integerForKey:MMTabOptimumWidthKey]]; + + [tabBarControl setAllowsDragBetweenWindows:NO]; + + [tablineSeparator setBoxType:NSBoxSeparator]; + [tablineSeparator setHidden:NO]; + [tablineSeparator setAutoresizingMask:NSViewWidthSizable + | NSViewMinYMargin]; + + [contentView setAutoresizesSubviews:YES]; + [contentView addSubview:tabBarControl]; + [contentView addSubview:tablineSeparator]; + + [[self window] setDelegate:self]; + [[self window] setInitialFirstResponder:textView]; +#endif } return self; @@ -151,29 +204,33 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) { //NSLog(@"%@ %s", [self className], _cmd); - // TODO: release tabBarControl and tabView? - - vimController = nil; - - [tabBarControl setDelegate:nil]; - [[self window] setDelegate:nil]; - - [tabView removeAllTabViewItems]; +#if MM_USE_EMPTY_WINDOW + [tabBarControl release]; tabBarControl = nil; + [tabView release]; tabView = nil; + [tablineSeparator release]; tablineSeparator = nil; +#endif + [windowAutosaveKey release]; windowAutosaveKey = nil; + [scrollbars release]; scrollbars = nil; + [textView release]; textView = nil; + [textStorage release]; textStorage = nil; - [scrollbars release]; - [textView release]; - [textStorage release]; + //[tabBarControl release]; tabBarControl = nil; + //[tabView release]; tabView = nil; [super dealloc]; } -- (void)windowDidLoad +- (NSString *)description { - NSWindow *win = [self window]; + return [NSString stringWithFormat:@"%@ : setupDone=%d windowAutosaveKey=%@ vimController=%@", [self className], setupDone, windowAutosaveKey, vimController]; +} +#if !MM_USE_EMPTY_WINDOW +- (void)windowDidLoad +{ // Called after window nib file is loaded. - [tablineSeparator setHidden:NO]; + [tablineSeparator setHidden:([[self window] toolbar] == nil)]; [tabBarControl setHidden:YES]; // NOTE: Size to fit looks good, but not many tabs will fit and there are @@ -186,29 +243,15 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) [tabBarControl setCellOptimumWidth:[ud integerForKey:MMTabOptimumWidthKey]]; [tabBarControl setAllowsDragBetweenWindows:NO]; - [tabBarControl setShowAddTabButton:YES]; - [[tabBarControl addTabButton] setTarget:self]; - [[tabBarControl addTabButton] setAction:@selector(addNewTab:)]; + //[tabBarControl setShowAddTabButton:YES]; + //[[tabBarControl addTabButton] setTarget:self]; + //[[tabBarControl addTabButton] setAction:@selector(addNewTab:)]; // HACK! remove any tabs present in the nib [tabView removeAllTabViewItems]; - - // HACK! These observers used to be set in the designated init of - // MMVimController, but this occasionally caused exceptions from within the - // AppKit to be raised. The problem seemed related to the fact that the - // window got loaded 'too early'; adding the observers here seems to - // alleviate this problem. - [[NSNotificationCenter defaultCenter] - addObserver:vimController - selector:@selector(windowWillClose:) - name:NSWindowWillCloseNotification - object:win]; - [[NSNotificationCenter defaultCenter] - addObserver:vimController - selector:@selector(windowDidBecomeMain:) - name:NSWindowDidBecomeMainNotification - object:win]; + [tabView setHidden:YES]; } +#endif - (MMVimController *)vimController { @@ -236,6 +279,44 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) windowAutosaveKey = [key copy]; } +- (void)cleanup +{ + //NSLog(@"%@ %s", [self className], _cmd); + + setupDone = NO; + vimController = nil; + + // NOTE! There is a bug in PSMTabBarControl in that it retains the delegate + // (which is the MMWindowController) so reset the delegate here, otherwise + // the MMWindowController never gets released resulting in a pretty serious + // memory leak. + [tabView setDelegate:nil]; + [tabBarControl setDelegate:nil]; + [tabBarControl setTabView:nil]; + [[self window] setDelegate:nil]; + + // NOTE! There is another bug in PSMTabBarControl where the control is not + // removed as an observer, so remove it here (else lots of evil nasty bugs + // will come and gnaw at your feet while you are sleeping). + [[NSNotificationCenter defaultCenter] removeObserver:tabBarControl]; + +#if MM_USE_EMPTY_WINDOW + [tabBarControl removeFromSuperviewWithoutNeedingDisplay]; + [tablineSeparator removeFromSuperviewWithoutNeedingDisplay]; +#endif + [textView removeFromSuperviewWithoutNeedingDisplay]; + + unsigned i, count = [scrollbars count]; + for (i = 0; i < count; ++i) { + MMScroller *sb = [scrollbars objectAtIndex:i]; + [sb removeFromSuperviewWithoutNeedingDisplay]; + } + + [tabView removeAllTabViewItems]; + + [[self window] orderOut:self]; +} + - (void)openWindow { [[NSApp delegate] windowControllerWillOpen:self]; @@ -245,15 +326,17 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) // NOTE! This flag is set once the entire text system is set up. setupDone = YES; - [self updateResizeIncrements]; - [self resizeWindowToFit:self]; - [[self window] makeKeyAndOrderFront:self]; - +#if !MM_USE_EMPTY_WINDOW BOOL statusOff = [[NSUserDefaults standardUserDefaults] boolForKey:MMStatuslineOffKey]; [statusTextField setHidden:statusOff]; [statusSeparator setHidden:statusOff]; [self flashStatusText:@"Welcome to MacVim!"]; +#endif + + [self updateResizeIncrements]; + [self resizeWindowToFit:self]; + [[self window] makeKeyAndOrderFront:self]; } - (void)updateTabsWithData:(NSData *)data @@ -339,14 +422,17 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) - (void)setStatusText:(NSString *)text { +#if !MM_USE_EMPTY_WINDOW if (text) [statusTextField setStringValue:text]; else [statusTextField setStringValue:@""]; +#endif } - (void)flashStatusText:(NSString *)text { +#if !MM_USE_EMPTY_WINDOW if ([[NSUserDefaults standardUserDefaults] boolForKey:MMStatuslineOffKey]) return; @@ -362,6 +448,7 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) selector:@selector(statusTimerFired:) userInfo:nil repeats:NO] retain]; +#endif } - (void)createScrollbarWithIdentifier:(long)ident type:(int)type @@ -517,15 +604,15 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) - (IBAction)addNewTab:(id)sender { -// NOTE! This can get called a lot if the user holds down the key -// equivalent for this action, which causes the ports to fill up. If we -// wait for the message to be sent then the app might become unresponsive. -[vimController sendMessage:AddNewTabMsgID data:nil wait:NO]; + // NOTE! This can get called a lot if the user holds down the key + // equivalent for this action, which causes the ports to fill up. If we + // wait for the message to be sent then the app might become unresponsive. + [vimController sendMessage:AddNewTabMsgID data:nil wait:NO]; } - (IBAction)toggleToolbar:(id)sender { -[vimController sendMessage:ToggleToolbarMsgID data:nil wait:NO]; + [vimController sendMessage:ToggleToolbarMsgID data:nil wait:NO]; } @@ -536,14 +623,16 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) - (void)tabView:(NSTabView *)theTabView didSelectTabViewItem: (NSTabViewItem *)tabViewItem { -// HACK! There seem to be a bug in NSTextView which results in the first -// responder not being set to the view of the tab item so it is done -// manually here. -[[self window] makeFirstResponder:[tabViewItem view]]; - -// HACK! The selection message should not be propagated to the VimTask if -// the VimTask selected the tab (e.g. as opposed the user clicking the -// tab). The delegate method has no way of knowing who initiated the +#if !MM_USE_EMPTY_WINDOW + // HACK! There seem to be a bug in NSTabView which results in the first + // responder not being set to the view of the tab item so it is done + // manually here. + //[[self window] makeFirstResponder:[tabViewItem view]]; +#endif + + // HACK! The selection message should not be propagated to the VimTask if + // the VimTask selected the tab (e.g. as opposed the user clicking the + // tab). The delegate method has no way of knowing who initiated the // selection so a flag is set when the VimTask initiated the selection. if (!vimTaskSelectedTab) { // Propagate the selection message to the VimTask. @@ -590,17 +679,6 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) return NO; } -- (void)windowWillClose:(NSNotification *)notification -{ - //NSLog(@"%@ %s", [self className], _cmd); - - // NOTE! There is a bug in PSMTabBarControl in that it retains the delegate - // (which is the MMWindowController) so reset the delegate here, otherwise - // the MMWindowController never gets released resulting in a pretty serious - // memory leak. - [tabBarControl setDelegate:nil]; -} - - (void)windowDidMove:(NSNotification *)notification { if (setupDone && windowAutosaveKey) { @@ -846,11 +924,6 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) // will automatically select the first tab added to a tab view. NSTabViewItem *tvi = [[NSTabViewItem alloc] initWithIdentifier:nil]; - [tvi setView:textView]; - - // BUG! This call seems to have no effect; see comment in - // tabView:didSelectTabViewItem:. - //[tvi setInitialFirstResponder:textView]; // NOTE: If this is the first tab it will be automatically selected. vimTaskSelectedTab = YES; @@ -939,8 +1012,7 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) { if (!setupDone) return; - NSRect tabViewFrame = [tabView frame]; - NSView *contentView = [[self window] contentView]; + NSRect textViewFrame = [textView frame]; BOOL lsbVisible = [self leftScrollbarVisible]; BOOL statusVisible = ![[NSUserDefaults standardUserDefaults] boolForKey:MMStatuslineOffKey]; @@ -994,28 +1066,28 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) // text view all the way to the right, otherwise it looks ugly when // the user drags the window to resize. if (i == leftmostSbIdx) { - float w = NSMaxX(tabViewFrame) - NSMaxX(rect); + float w = NSMaxX(textViewFrame) - NSMaxX(rect); if (w > 0) rect.size.width += w; } - // Make sure scrollbar rect is bounded by the tab view frame. - if (rect.origin.x < tabViewFrame.origin.x) - rect.origin.x = tabViewFrame.origin.x; - else if (rect.origin.x > NSMaxX(tabViewFrame)) - rect.origin.x = NSMaxX(tabViewFrame); - if (NSMaxX(rect) > NSMaxX(tabViewFrame)) - rect.size.width -= NSMaxX(rect) - NSMaxX(tabViewFrame); + // Make sure scrollbar rect is bounded by the text view frame. + if (rect.origin.x < textViewFrame.origin.x) + rect.origin.x = textViewFrame.origin.x; + else if (rect.origin.x > NSMaxX(textViewFrame)) + rect.origin.x = NSMaxX(textViewFrame); + if (NSMaxX(rect) > NSMaxX(textViewFrame)) + rect.size.width -= NSMaxX(rect) - NSMaxX(textViewFrame); if (rect.size.width < 0) rect.size.width = 0; } else { rect = [textStorage rectForRowsInRange:[scroller range]]; // Adjust for the fact that text layout is flipped. - rect.origin.y = NSMaxY(tabViewFrame) - rect.origin.y + rect.origin.y = NSMaxY(textViewFrame) - rect.origin.y - rect.size.height; rect.size.width = [NSScroller scrollerWidth]; if ([scroller type] == MMScrollerTypeRight) - rect.origin.x = NSMaxX(tabViewFrame); + rect.origin.x = NSMaxX(textViewFrame); // HACK! Make sure the lowest vertical scrollbar covers the text // view all the way to the bottom. This is done because Vim only @@ -1025,9 +1097,9 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) // TODO! Find a nicer way to do this. if (i == lowestLeftSbIdx || i == lowestRightSbIdx) { float h = rect.origin.y + rect.size.height - - tabViewFrame.origin.y; + - textViewFrame.origin.y; if (rect.size.height < h) { - rect.origin.y = tabViewFrame.origin.y; + rect.origin.y = textViewFrame.origin.y; rect.size.height = h; } } @@ -1039,14 +1111,14 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) rect.origin.y = [NSScroller scrollerWidth]; } - // Make sure scrollbar rect is bounded by the tab view frame. - if (rect.origin.y < tabViewFrame.origin.y) { - rect.size.height -= tabViewFrame.origin.y - rect.origin.y; - rect.origin.y = tabViewFrame.origin.y; - } else if (rect.origin.y > NSMaxY(tabViewFrame)) - rect.origin.y = NSMaxY(tabViewFrame); - if (NSMaxY(rect) > NSMaxY(tabViewFrame)) - rect.size.height -= NSMaxY(rect) - NSMaxY(tabViewFrame); + // Make sure scrollbar rect is bounded by the text view frame. + if (rect.origin.y < textViewFrame.origin.y) { + rect.size.height -= textViewFrame.origin.y - rect.origin.y; + rect.origin.y = textViewFrame.origin.y; + } else if (rect.origin.y > NSMaxY(textViewFrame)) + rect.origin.y = NSMaxY(textViewFrame); + if (NSMaxY(rect) > NSMaxY(textViewFrame)) + rect.size.height -= NSMaxY(rect) - NSMaxY(textViewFrame); if (rect.size.height < 0) rect.size.height = 0; } @@ -1057,7 +1129,7 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) [scroller setFrame:rect]; // Clear behind the old scroller frame, or parts of the old // scroller might still be visible after setFrame:. - [contentView setNeedsDisplayInRect:oldRect]; + [[[self window] contentView] setNeedsDisplayInRect:oldRect]; [scroller setNeedsDisplay:YES]; } } @@ -1108,7 +1180,7 @@ NSMutableArray *buildMenuAddress(NSMenu *menu) wait:![textView inLiveResize]]; } - [tabView setFrame:textViewRect]; + [textView setFrame:textViewRect]; [self placeScrollbars]; } -- 2.11.4.GIT