From 7dd70040ee41a643b3256695100f7e3d182684cd Mon Sep 17 00:00:00 2001 From: "pinkerton%netscape.com" Date: Thu, 1 Aug 2002 18:00:50 +0000 Subject: [PATCH] Keep XPCOM from being shut down while this window is open (bug 160241) --- .../MVPreferencesController.mm | 368 ------------------ .../preferences/MVPreferencesController.mm | 12 + .../MVPreferencesController.mm | 368 ------------------ .../preferences/MVPreferencesController.mm | 12 + 4 files changed, 24 insertions(+), 736 deletions(-) diff --git a/camino/PreferencePanes/MVPreferencesController.mm b/camino/PreferencePanes/MVPreferencesController.mm index 50ace57f546..e69de29bb2d 100644 --- a/camino/PreferencePanes/MVPreferencesController.mm +++ b/camino/PreferencePanes/MVPreferencesController.mm @@ -1,368 +0,0 @@ -#import -#import "MVPreferencesController.h" -#import "MVPreferencesMultipleIconView.h" -#import "MVPreferencesGroupedIconView.h" -#import "CHToolbarAdditions.h" - -#include "nsCOMPtr.h" -#include "nsIServiceManager.h" -#include "nsIPref.h" - -// #import "Defines.h" - -static MVPreferencesController *sharedInstance = nil; - -NSString *MVToolbarShowAllItemIdentifier = @"MVToolbarShowAllItem"; -NSString *MVPreferencesWindowNotification = @"MVPreferencesWindowNotification"; - -@interface NSToolbar (NSToolbarPrivate) -- (NSView *) _toolbarView; -@end - -@interface MVPreferencesController (MVPreferencesControllerPrivate) -- (void) _doUnselect:(NSNotification *) notification; -- (IBAction) _selectPreferencePane:(id) sender; -- (void) _resizeWindowForContentView:(NSView *) view; -- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle; -- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle; -- (NSString *) _labelForPaneBundle:(NSBundle *) bundle; -@end - -@implementation MVPreferencesController - -+ (MVPreferencesController *) sharedInstance -{ - return ( sharedInstance ? sharedInstance : [[[self alloc] init] autorelease] ); -} - -- (id) init -{ - if ( ( self = [super init] ) ) { - unsigned i = 0; - NSBundle *bundle = nil; - NSString *bundlePath = [NSString stringWithFormat:@"%@/Contents/PreferencePanes", - [[NSBundle mainBundle] bundlePath]]; - panes = [[[NSFileManager defaultManager] directoryContentsAtPath:bundlePath] mutableCopy]; - for ( i = 0; i < [panes count]; i++ ) { - bundle = [NSBundle bundleWithPath:[NSString stringWithFormat:@"%@/%@", bundlePath, [panes objectAtIndex:i]]]; - [bundle load]; - if( bundle ) [panes replaceObjectAtIndex:i withObject:bundle]; - else { - [panes removeObjectAtIndex:i]; - i--; - } - } - loadedPanes = [[NSMutableDictionary dictionary] retain]; - paneInfo = [[NSMutableDictionary dictionary] retain]; - [NSBundle loadNibNamed:@"MVPreferences" owner:self]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _doUnselect: ) name:NSPreferencePaneDoUnselectNotification object:nil]; - } - return self; -} - -- (void) dealloc -{ - [loadedPanes autorelease]; - [panes autorelease]; - [paneInfo autorelease]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - loadedPanes = nil; - panes = nil; - paneInfo = nil; - [super dealloc]; -} - -- (void) awakeFromNib -{ - NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:@"preferences.toolbar"] autorelease]; - NSArray *groups = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MVPreferencePaneGroups" ofType:@"plist"]]; - - if( groups ) { - [groupView setPreferencePanes:panes]; - [groupView setPreferencePaneGroups:groups]; - mainView = groupView; - } else { - [multiView setPreferencePanes:panes]; - mainView = multiView; - } - [self showAll:nil]; - - [window setDelegate:self]; - - [toolbar setAllowsUserCustomization:YES]; - [toolbar setAutosavesConfiguration:YES]; - [toolbar setDelegate:self]; - [toolbar setAlwaysCustomizableByDrag:YES]; - [toolbar setShowsContextMenu:NO]; - [window setToolbar:toolbar]; - [toolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel]; - [toolbar setIndexOfFirstMovableItem:2]; -} - -- (NSWindow *) window -{ - return [[window retain] autorelease]; -} - -- (IBAction) showPreferences:(id) sender -{ - [self showAll:nil]; - [window makeKeyAndOrderFront:nil]; -} - -- (IBAction) showAll:(id) sender -{ - if ( [[window contentView] isEqual:mainView] ) return; - if ( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { - /* more to handle later */ -#if DEBUG - NSLog( @"can't unselect current" ); -#endif - return; - } - [window setContentView:[[[NSView alloc] initWithFrame:[mainView frame]] autorelease]]; - - [window setTitle:[NSString stringWithFormat:NSLocalizedString( @"%@ Preferences", nil ), [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]]]; - [self _resizeWindowForContentView:mainView]; - - [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; - [window setContentView:mainView]; - [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; - - [currentPaneIdentifier autorelease]; - currentPaneIdentifier = nil; - - [window setInitialFirstResponder:mainView]; - [window makeFirstResponder:mainView]; -} - -- (void) selectPreferencePaneByIdentifier:(NSString *) identifier -{ - NSBundle *bundle = [NSBundle bundleWithIdentifier:identifier]; - - if ( bundle && ! [currentPaneIdentifier isEqualToString:identifier] ) { - NSPreferencePane *pane = nil; - NSView *prefView = nil; - if ( currentPaneIdentifier && - [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { - /* more to handle later */ -#if DEBUG - NSLog( @"can't unselect current" ); -#endif - closeWhenPaneIsReady = NO; - [pendingPane autorelease]; - pendingPane = [identifier retain]; - return; - } - - [pendingPane autorelease]; - pendingPane = nil; - [loadingImageView setImage:[self _imageForPaneBundle:bundle]]; - [loadingTextFeld setStringValue:[NSString stringWithFormat:NSLocalizedString( @"Loading %@...", nil ), - [self _labelForPaneBundle:bundle]]]; - - [window setTitle:[self _labelForPaneBundle:bundle]]; - [window setContentView:loadingView]; - [window display]; - - if ( ! ( pane = [loadedPanes objectForKey:identifier] ) ) { - pane = [[[[bundle principalClass] alloc] initWithBundle:bundle] autorelease]; - if( pane ) [loadedPanes setObject:pane forKey:identifier]; - } - - if ( [pane loadMainView] ) { - [pane willSelect]; - prefView = [pane mainView]; - - [self _resizeWindowForContentView:prefView]; - - [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; - [window setContentView:prefView]; - [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; - [pane didSelect]; - [[NSNotificationCenter defaultCenter] - postNotificationName: MVPreferencesWindowNotification - object: self - userInfo: [NSDictionary dictionaryWithObjectsAndKeys:window, @"window", nil]]; - [currentPaneIdentifier autorelease]; - currentPaneIdentifier = [identifier copy]; - - [window setInitialFirstResponder:[pane initialKeyView]]; - [window makeFirstResponder:[pane initialKeyView]]; - } - else { - NSRunCriticalAlertPanel( NSLocalizedString( @"Preferences Error", nil ), - [NSString stringWithFormat:NSLocalizedString( @"Could not load %@", nil ), - [self _labelForPaneBundle:bundle]], nil, nil, nil ); - } - } -} - -- (BOOL) windowShouldClose:(id) sender -{ - if ( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { -#if DEBUG - NSLog( @"can't unselect current" ); -#endif - closeWhenPaneIsReady = YES; - return NO; - } - return YES; -} - -- (void) windowWillClose:(NSNotification *) notification -{ - [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; - [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; - [currentPaneIdentifier autorelease]; - currentPaneIdentifier = nil; - //[loadedPanes removeAllObjects]; - - // write out prefs and user defaults - nsCOMPtr prefService ( do_GetService(NS_PREF_CONTRACTID) ); - NS_ASSERTION(prefService, "Could not get pref service, prefs unsaved"); - if ( prefService ) - prefService->SavePrefFile(nsnull); // nsnull means write to prefs.js - [[NSUserDefaults standardUserDefaults] synchronize]; -} - -- (NSToolbarItem *) toolbar:(NSToolbar *) toolbar - itemForItemIdentifier:(NSString *) itemIdentifier - willBeInsertedIntoToolbar:(BOOL) flag -{ - NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease]; - if ( [itemIdentifier isEqualToString:MVToolbarShowAllItemIdentifier] ) { - [toolbarItem setLabel:NSLocalizedString( @"Show All", nil )]; - [toolbarItem setImage:[NSImage imageNamed:@"NSApplicationIcon"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector( showAll: )]; - } else { - NSBundle *bundle = [NSBundle bundleWithIdentifier:itemIdentifier]; - if( bundle ) { - [toolbarItem setLabel:[self _labelForPaneBundle:bundle]]; - [toolbarItem setPaletteLabel:[self _paletteLabelForPaneBundle:bundle]]; - [toolbarItem setImage:[self _imageForPaneBundle:bundle]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector( _selectPreferencePane: )]; - } else toolbarItem = nil; - } - return toolbarItem; -} - -- (NSArray *) toolbarDefaultItemIdentifiers:(NSToolbar *) toolbar -{ - NSMutableArray *fixed = [NSMutableArray arrayWithObjects:MVToolbarShowAllItemIdentifier, NSToolbarSeparatorItemIdentifier, nil]; - NSArray *defaults = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MVPreferencePaneDefaults" ofType:@"plist"]]; - [fixed addObjectsFromArray:defaults]; - return fixed; -} - -- (NSArray *) toolbarAllowedItemIdentifiers:(NSToolbar *) toolbar -{ - NSMutableArray *items = [NSMutableArray array]; - NSEnumerator *enumerator = [panes objectEnumerator]; - id item = nil; - while ( ( item = [enumerator nextObject] ) ) - [items addObject:[item bundleIdentifier]]; - //[items addObject:MVToolbarShowAllItemIdentifier]; - [items addObject:NSToolbarSeparatorItemIdentifier]; - return items; -} - -@end - -@implementation MVPreferencesController (MVPreferencesControllerPrivate) - -- (IBAction) _selectPreferencePane:(id) sender -{ - [self selectPreferencePaneByIdentifier:[sender itemIdentifier]]; -} - -- (void) _doUnselect:(NSNotification *) notification -{ - if( closeWhenPaneIsReady ) [window close]; - [self selectPreferencePaneByIdentifier:pendingPane]; -} - -- (void) _resizeWindowForContentView:(NSView *) view -{ - NSRect windowFrame, newWindowFrame; - unsigned int newWindowHeight; - - windowFrame = [NSWindow contentRectForFrameRect:[window frame] styleMask:[window styleMask]]; - newWindowHeight = NSHeight( [view frame] ); - if ( [[window toolbar] isVisible] ) - newWindowHeight += NSHeight( [[[window toolbar] _toolbarView] frame] ); - newWindowFrame = [NSWindow frameRectForContentRect:NSMakeRect( NSMinX( windowFrame ), NSMaxY( windowFrame ) - newWindowHeight, NSWidth( windowFrame ), newWindowHeight ) styleMask:[window styleMask]]; - - [window setFrame:newWindowFrame display:YES animate:[window isVisible]]; -} - -- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle -{ - NSImage *image = nil; - NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - image = [[[cache objectForKey:@"MVPreferencePaneImage"] retain] autorelease]; - if ( ! image ) { - NSDictionary *info = [bundle infoDictionary]; - image = [[[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:[info objectForKey:@"NSPrefPaneIconFile"]]] autorelease]; - if ( ! image ) image = [[[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:[info objectForKey:@"CFBundleIconFile"]]] autorelease]; - if ( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; - cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - if ( image ) [cache setObject:image forKey:@"MVPreferencePaneImage"]; - } - return image; -} - -- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle -{ - NSString *label = nil; - NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - label = [[[cache objectForKey:@"MVPreferencePanePaletteLabel"] retain] autorelease]; - if ( ! label ) { - NSDictionary *info = [bundle infoDictionary]; - label = NSLocalizedStringFromTableInBundle( @"NSPrefPaneIconLabel", @"InfoPlist", bundle, nil ); - if ( [label isEqualToString:@"NSPrefPaneIconLabel"] ) label = [info objectForKey:@"NSPrefPaneIconLabel"]; - if ( ! label ) label = NSLocalizedStringFromTableInBundle( @"CFBundleName", @"InfoPlist", bundle, nil ); - if ( [label isEqualToString:@"CFBundleName"] ) label = [info objectForKey:@"CFBundleName"]; - if ( ! label ) label = [bundle bundleIdentifier]; - if ( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; - cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - if ( label ) [cache setObject:label forKey:@"MVPreferencePanePaletteLabel"]; - } - return label; -} - -- (NSString *) _labelForPaneBundle:(NSBundle *) bundle -{ - NSString *label = nil; - NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - label = [[[cache objectForKey:@"MVPreferencePaneLabel"] retain] autorelease]; - if ( ! label ) { - NSDictionary *info = [bundle infoDictionary]; - label = NSLocalizedStringFromTableInBundle( @"CFBundleName", @"InfoPlist", bundle, nil ); - if ( [label isEqualToString:@"CFBundleName"] ) label = [info objectForKey:@"CFBundleName"]; - if ( ! label ) label = [bundle bundleIdentifier]; - if ( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; - cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - if ( label ) [cache setObject:label forKey:@"MVPreferencePaneLabel"]; - } - return label; -} -@end - -// When using the Font Panel without an obvious target (like an editable text field), -// changeFont action messages propagate all the way up the responder chain to here. -// There isn't an easy way for individual prefs panes to get themselves into -// the responder chain, so we just bounce this message back to the currently -// loaded pane. -@implementation MVPreferencesController (FontChangeNotifications) - -- (void)changeFont:(id)sender -{ - [[loadedPanes objectForKey:currentPaneIdentifier] changeFont:sender]; -} - -@end - diff --git a/camino/src/preferences/MVPreferencesController.mm b/camino/src/preferences/MVPreferencesController.mm index 50ace57f546..6719b1ff9aa 100644 --- a/camino/src/preferences/MVPreferencesController.mm +++ b/camino/src/preferences/MVPreferencesController.mm @@ -7,6 +7,7 @@ #include "nsCOMPtr.h" #include "nsIServiceManager.h" #include "nsIPref.h" +#include "nsCocoaBrowserService.h" // #import "Defines.h" @@ -70,6 +71,7 @@ NSString *MVPreferencesWindowNotification = @"MVPreferencesWindowNotification"; loadedPanes = nil; panes = nil; paneInfo = nil; + [super dealloc]; } @@ -107,6 +109,13 @@ NSString *MVPreferencesWindowNotification = @"MVPreferencesWindowNotification"; - (IBAction) showPreferences:(id) sender { + if ( ![window isVisible] ) { + // on being shown, register as a window that cares about XPCOM being active until we're done + // with it in |windowDidClose()|. Need to ensure this is exactly balanced with |BrowserClosed()| + // calls as it increments a refcount. As a result, we can only call it when we're making + // the window visible. Too bad cocoa doesn't give us any notifications of this. + nsCocoaBrowserService::InitEmbedding(); + } [self showAll:nil]; [window makeKeyAndOrderFront:nil]; } @@ -225,6 +234,9 @@ NSString *MVPreferencesWindowNotification = @"MVPreferencesWindowNotification"; if ( prefService ) prefService->SavePrefFile(nsnull); // nsnull means write to prefs.js [[NSUserDefaults standardUserDefaults] synchronize]; + + // tell gecko that this window no longer needs it around. + nsCocoaBrowserService::BrowserClosed(); } - (NSToolbarItem *) toolbar:(NSToolbar *) toolbar diff --git a/chimera/PreferencePanes/MVPreferencesController.mm b/chimera/PreferencePanes/MVPreferencesController.mm index 50ace57f546..e69de29bb2d 100644 --- a/chimera/PreferencePanes/MVPreferencesController.mm +++ b/chimera/PreferencePanes/MVPreferencesController.mm @@ -1,368 +0,0 @@ -#import -#import "MVPreferencesController.h" -#import "MVPreferencesMultipleIconView.h" -#import "MVPreferencesGroupedIconView.h" -#import "CHToolbarAdditions.h" - -#include "nsCOMPtr.h" -#include "nsIServiceManager.h" -#include "nsIPref.h" - -// #import "Defines.h" - -static MVPreferencesController *sharedInstance = nil; - -NSString *MVToolbarShowAllItemIdentifier = @"MVToolbarShowAllItem"; -NSString *MVPreferencesWindowNotification = @"MVPreferencesWindowNotification"; - -@interface NSToolbar (NSToolbarPrivate) -- (NSView *) _toolbarView; -@end - -@interface MVPreferencesController (MVPreferencesControllerPrivate) -- (void) _doUnselect:(NSNotification *) notification; -- (IBAction) _selectPreferencePane:(id) sender; -- (void) _resizeWindowForContentView:(NSView *) view; -- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle; -- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle; -- (NSString *) _labelForPaneBundle:(NSBundle *) bundle; -@end - -@implementation MVPreferencesController - -+ (MVPreferencesController *) sharedInstance -{ - return ( sharedInstance ? sharedInstance : [[[self alloc] init] autorelease] ); -} - -- (id) init -{ - if ( ( self = [super init] ) ) { - unsigned i = 0; - NSBundle *bundle = nil; - NSString *bundlePath = [NSString stringWithFormat:@"%@/Contents/PreferencePanes", - [[NSBundle mainBundle] bundlePath]]; - panes = [[[NSFileManager defaultManager] directoryContentsAtPath:bundlePath] mutableCopy]; - for ( i = 0; i < [panes count]; i++ ) { - bundle = [NSBundle bundleWithPath:[NSString stringWithFormat:@"%@/%@", bundlePath, [panes objectAtIndex:i]]]; - [bundle load]; - if( bundle ) [panes replaceObjectAtIndex:i withObject:bundle]; - else { - [panes removeObjectAtIndex:i]; - i--; - } - } - loadedPanes = [[NSMutableDictionary dictionary] retain]; - paneInfo = [[NSMutableDictionary dictionary] retain]; - [NSBundle loadNibNamed:@"MVPreferences" owner:self]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _doUnselect: ) name:NSPreferencePaneDoUnselectNotification object:nil]; - } - return self; -} - -- (void) dealloc -{ - [loadedPanes autorelease]; - [panes autorelease]; - [paneInfo autorelease]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - loadedPanes = nil; - panes = nil; - paneInfo = nil; - [super dealloc]; -} - -- (void) awakeFromNib -{ - NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:@"preferences.toolbar"] autorelease]; - NSArray *groups = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MVPreferencePaneGroups" ofType:@"plist"]]; - - if( groups ) { - [groupView setPreferencePanes:panes]; - [groupView setPreferencePaneGroups:groups]; - mainView = groupView; - } else { - [multiView setPreferencePanes:panes]; - mainView = multiView; - } - [self showAll:nil]; - - [window setDelegate:self]; - - [toolbar setAllowsUserCustomization:YES]; - [toolbar setAutosavesConfiguration:YES]; - [toolbar setDelegate:self]; - [toolbar setAlwaysCustomizableByDrag:YES]; - [toolbar setShowsContextMenu:NO]; - [window setToolbar:toolbar]; - [toolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel]; - [toolbar setIndexOfFirstMovableItem:2]; -} - -- (NSWindow *) window -{ - return [[window retain] autorelease]; -} - -- (IBAction) showPreferences:(id) sender -{ - [self showAll:nil]; - [window makeKeyAndOrderFront:nil]; -} - -- (IBAction) showAll:(id) sender -{ - if ( [[window contentView] isEqual:mainView] ) return; - if ( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { - /* more to handle later */ -#if DEBUG - NSLog( @"can't unselect current" ); -#endif - return; - } - [window setContentView:[[[NSView alloc] initWithFrame:[mainView frame]] autorelease]]; - - [window setTitle:[NSString stringWithFormat:NSLocalizedString( @"%@ Preferences", nil ), [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]]]; - [self _resizeWindowForContentView:mainView]; - - [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; - [window setContentView:mainView]; - [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; - - [currentPaneIdentifier autorelease]; - currentPaneIdentifier = nil; - - [window setInitialFirstResponder:mainView]; - [window makeFirstResponder:mainView]; -} - -- (void) selectPreferencePaneByIdentifier:(NSString *) identifier -{ - NSBundle *bundle = [NSBundle bundleWithIdentifier:identifier]; - - if ( bundle && ! [currentPaneIdentifier isEqualToString:identifier] ) { - NSPreferencePane *pane = nil; - NSView *prefView = nil; - if ( currentPaneIdentifier && - [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { - /* more to handle later */ -#if DEBUG - NSLog( @"can't unselect current" ); -#endif - closeWhenPaneIsReady = NO; - [pendingPane autorelease]; - pendingPane = [identifier retain]; - return; - } - - [pendingPane autorelease]; - pendingPane = nil; - [loadingImageView setImage:[self _imageForPaneBundle:bundle]]; - [loadingTextFeld setStringValue:[NSString stringWithFormat:NSLocalizedString( @"Loading %@...", nil ), - [self _labelForPaneBundle:bundle]]]; - - [window setTitle:[self _labelForPaneBundle:bundle]]; - [window setContentView:loadingView]; - [window display]; - - if ( ! ( pane = [loadedPanes objectForKey:identifier] ) ) { - pane = [[[[bundle principalClass] alloc] initWithBundle:bundle] autorelease]; - if( pane ) [loadedPanes setObject:pane forKey:identifier]; - } - - if ( [pane loadMainView] ) { - [pane willSelect]; - prefView = [pane mainView]; - - [self _resizeWindowForContentView:prefView]; - - [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; - [window setContentView:prefView]; - [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; - [pane didSelect]; - [[NSNotificationCenter defaultCenter] - postNotificationName: MVPreferencesWindowNotification - object: self - userInfo: [NSDictionary dictionaryWithObjectsAndKeys:window, @"window", nil]]; - [currentPaneIdentifier autorelease]; - currentPaneIdentifier = [identifier copy]; - - [window setInitialFirstResponder:[pane initialKeyView]]; - [window makeFirstResponder:[pane initialKeyView]]; - } - else { - NSRunCriticalAlertPanel( NSLocalizedString( @"Preferences Error", nil ), - [NSString stringWithFormat:NSLocalizedString( @"Could not load %@", nil ), - [self _labelForPaneBundle:bundle]], nil, nil, nil ); - } - } -} - -- (BOOL) windowShouldClose:(id) sender -{ - if ( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { -#if DEBUG - NSLog( @"can't unselect current" ); -#endif - closeWhenPaneIsReady = YES; - return NO; - } - return YES; -} - -- (void) windowWillClose:(NSNotification *) notification -{ - [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; - [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; - [currentPaneIdentifier autorelease]; - currentPaneIdentifier = nil; - //[loadedPanes removeAllObjects]; - - // write out prefs and user defaults - nsCOMPtr prefService ( do_GetService(NS_PREF_CONTRACTID) ); - NS_ASSERTION(prefService, "Could not get pref service, prefs unsaved"); - if ( prefService ) - prefService->SavePrefFile(nsnull); // nsnull means write to prefs.js - [[NSUserDefaults standardUserDefaults] synchronize]; -} - -- (NSToolbarItem *) toolbar:(NSToolbar *) toolbar - itemForItemIdentifier:(NSString *) itemIdentifier - willBeInsertedIntoToolbar:(BOOL) flag -{ - NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease]; - if ( [itemIdentifier isEqualToString:MVToolbarShowAllItemIdentifier] ) { - [toolbarItem setLabel:NSLocalizedString( @"Show All", nil )]; - [toolbarItem setImage:[NSImage imageNamed:@"NSApplicationIcon"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector( showAll: )]; - } else { - NSBundle *bundle = [NSBundle bundleWithIdentifier:itemIdentifier]; - if( bundle ) { - [toolbarItem setLabel:[self _labelForPaneBundle:bundle]]; - [toolbarItem setPaletteLabel:[self _paletteLabelForPaneBundle:bundle]]; - [toolbarItem setImage:[self _imageForPaneBundle:bundle]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector( _selectPreferencePane: )]; - } else toolbarItem = nil; - } - return toolbarItem; -} - -- (NSArray *) toolbarDefaultItemIdentifiers:(NSToolbar *) toolbar -{ - NSMutableArray *fixed = [NSMutableArray arrayWithObjects:MVToolbarShowAllItemIdentifier, NSToolbarSeparatorItemIdentifier, nil]; - NSArray *defaults = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MVPreferencePaneDefaults" ofType:@"plist"]]; - [fixed addObjectsFromArray:defaults]; - return fixed; -} - -- (NSArray *) toolbarAllowedItemIdentifiers:(NSToolbar *) toolbar -{ - NSMutableArray *items = [NSMutableArray array]; - NSEnumerator *enumerator = [panes objectEnumerator]; - id item = nil; - while ( ( item = [enumerator nextObject] ) ) - [items addObject:[item bundleIdentifier]]; - //[items addObject:MVToolbarShowAllItemIdentifier]; - [items addObject:NSToolbarSeparatorItemIdentifier]; - return items; -} - -@end - -@implementation MVPreferencesController (MVPreferencesControllerPrivate) - -- (IBAction) _selectPreferencePane:(id) sender -{ - [self selectPreferencePaneByIdentifier:[sender itemIdentifier]]; -} - -- (void) _doUnselect:(NSNotification *) notification -{ - if( closeWhenPaneIsReady ) [window close]; - [self selectPreferencePaneByIdentifier:pendingPane]; -} - -- (void) _resizeWindowForContentView:(NSView *) view -{ - NSRect windowFrame, newWindowFrame; - unsigned int newWindowHeight; - - windowFrame = [NSWindow contentRectForFrameRect:[window frame] styleMask:[window styleMask]]; - newWindowHeight = NSHeight( [view frame] ); - if ( [[window toolbar] isVisible] ) - newWindowHeight += NSHeight( [[[window toolbar] _toolbarView] frame] ); - newWindowFrame = [NSWindow frameRectForContentRect:NSMakeRect( NSMinX( windowFrame ), NSMaxY( windowFrame ) - newWindowHeight, NSWidth( windowFrame ), newWindowHeight ) styleMask:[window styleMask]]; - - [window setFrame:newWindowFrame display:YES animate:[window isVisible]]; -} - -- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle -{ - NSImage *image = nil; - NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - image = [[[cache objectForKey:@"MVPreferencePaneImage"] retain] autorelease]; - if ( ! image ) { - NSDictionary *info = [bundle infoDictionary]; - image = [[[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:[info objectForKey:@"NSPrefPaneIconFile"]]] autorelease]; - if ( ! image ) image = [[[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:[info objectForKey:@"CFBundleIconFile"]]] autorelease]; - if ( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; - cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - if ( image ) [cache setObject:image forKey:@"MVPreferencePaneImage"]; - } - return image; -} - -- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle -{ - NSString *label = nil; - NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - label = [[[cache objectForKey:@"MVPreferencePanePaletteLabel"] retain] autorelease]; - if ( ! label ) { - NSDictionary *info = [bundle infoDictionary]; - label = NSLocalizedStringFromTableInBundle( @"NSPrefPaneIconLabel", @"InfoPlist", bundle, nil ); - if ( [label isEqualToString:@"NSPrefPaneIconLabel"] ) label = [info objectForKey:@"NSPrefPaneIconLabel"]; - if ( ! label ) label = NSLocalizedStringFromTableInBundle( @"CFBundleName", @"InfoPlist", bundle, nil ); - if ( [label isEqualToString:@"CFBundleName"] ) label = [info objectForKey:@"CFBundleName"]; - if ( ! label ) label = [bundle bundleIdentifier]; - if ( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; - cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - if ( label ) [cache setObject:label forKey:@"MVPreferencePanePaletteLabel"]; - } - return label; -} - -- (NSString *) _labelForPaneBundle:(NSBundle *) bundle -{ - NSString *label = nil; - NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - label = [[[cache objectForKey:@"MVPreferencePaneLabel"] retain] autorelease]; - if ( ! label ) { - NSDictionary *info = [bundle infoDictionary]; - label = NSLocalizedStringFromTableInBundle( @"CFBundleName", @"InfoPlist", bundle, nil ); - if ( [label isEqualToString:@"CFBundleName"] ) label = [info objectForKey:@"CFBundleName"]; - if ( ! label ) label = [bundle bundleIdentifier]; - if ( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; - cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; - if ( label ) [cache setObject:label forKey:@"MVPreferencePaneLabel"]; - } - return label; -} -@end - -// When using the Font Panel without an obvious target (like an editable text field), -// changeFont action messages propagate all the way up the responder chain to here. -// There isn't an easy way for individual prefs panes to get themselves into -// the responder chain, so we just bounce this message back to the currently -// loaded pane. -@implementation MVPreferencesController (FontChangeNotifications) - -- (void)changeFont:(id)sender -{ - [[loadedPanes objectForKey:currentPaneIdentifier] changeFont:sender]; -} - -@end - diff --git a/chimera/src/preferences/MVPreferencesController.mm b/chimera/src/preferences/MVPreferencesController.mm index 50ace57f546..6719b1ff9aa 100644 --- a/chimera/src/preferences/MVPreferencesController.mm +++ b/chimera/src/preferences/MVPreferencesController.mm @@ -7,6 +7,7 @@ #include "nsCOMPtr.h" #include "nsIServiceManager.h" #include "nsIPref.h" +#include "nsCocoaBrowserService.h" // #import "Defines.h" @@ -70,6 +71,7 @@ NSString *MVPreferencesWindowNotification = @"MVPreferencesWindowNotification"; loadedPanes = nil; panes = nil; paneInfo = nil; + [super dealloc]; } @@ -107,6 +109,13 @@ NSString *MVPreferencesWindowNotification = @"MVPreferencesWindowNotification"; - (IBAction) showPreferences:(id) sender { + if ( ![window isVisible] ) { + // on being shown, register as a window that cares about XPCOM being active until we're done + // with it in |windowDidClose()|. Need to ensure this is exactly balanced with |BrowserClosed()| + // calls as it increments a refcount. As a result, we can only call it when we're making + // the window visible. Too bad cocoa doesn't give us any notifications of this. + nsCocoaBrowserService::InitEmbedding(); + } [self showAll:nil]; [window makeKeyAndOrderFront:nil]; } @@ -225,6 +234,9 @@ NSString *MVPreferencesWindowNotification = @"MVPreferencesWindowNotification"; if ( prefService ) prefService->SavePrefFile(nsnull); // nsnull means write to prefs.js [[NSUserDefaults standardUserDefaults] synchronize]; + + // tell gecko that this window no longer needs it around. + nsCocoaBrowserService::BrowserClosed(); } - (NSToolbarItem *) toolbar:(NSToolbar *) toolbar