Bug 436063 - Don't manually build the window list in the Dock menu. Instead call [NSApp setWindowsMenu:] during startup so that Cocoa will build the list for us. r=josh

This commit is contained in:
Markus Stange 2010-05-01 12:42:47 +02:00
Родитель 481331354a
Коммит a1c21c98d2
1 изменённых файлов: 10 добавлений и 90 удалений

Просмотреть файл

@ -48,10 +48,7 @@
#import <Carbon/Carbon.h>
#include "nsCOMPtr.h"
#include "nsIBaseWindow.h"
#include "nsINativeAppSupport.h"
#include "nsIWidget.h"
#include "nsIWindowMediator.h"
#include "nsAppRunner.h"
#include "nsComponentManagerUtils.h"
#include "nsCommandLineServiceMac.h"
@ -104,7 +101,7 @@ SetupMacApplicationDelegate()
// Create the delegate. This should be around for the lifetime of the app.
MacApplicationDelegate *delegate = [[MacApplicationDelegate alloc] init];
[[NSApplication sharedApplication] setDelegate:delegate];
[NSApp setDelegate:delegate];
[pool release];
@ -129,6 +126,14 @@ SetupMacApplicationDelegate()
andSelector:@selector(handleAppleEvent:withReplyEvent:)
forEventClass:'WWW!'
andEventID:'OURL'];
if (![NSApp windowsMenu]) {
// If the application has a windows menu, it will keep it up to date and
// prepend the window list to the Dock menu automatically.
NSMenu* windowsMenu = [[NSMenu alloc] initWithTitle:@"Window"];
[NSApp setWindowsMenu:windowsMenu];
[windowsMenu release];
}
}
return self;
@ -205,92 +210,19 @@ SetupMacApplicationDelegate()
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
}
// Drill down from nsIXULWindow and get an NSWindow. We get passed nsISupports
// because that's what nsISimpleEnumerator returns.
static NSWindow* GetCocoaWindowForXULWindow(nsISupports *aXULWindow)
{
nsresult rv;
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(aXULWindow, &rv);
NS_ENSURE_SUCCESS(rv, nil);
nsCOMPtr<nsIWidget> widget;
rv = baseWindow->GetMainWidget(getter_AddRefs(widget));
NS_ENSURE_SUCCESS(rv, nil);
// If it fails, we return nil anyway, no biggie
return (NSWindow *)widget->GetNativeData(NS_NATIVE_WINDOW);
}
// Create the menu that shows up in the Dock.
- (NSMenu*)applicationDockMenu:(NSApplication*)sender
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
// Why we're not just using Cocoa to enumerate our windows:
// The Dock thinks we're a Carbon app, probably because we don't have a
// blessed Window menu, so we get none of the automatic handling for dock
// menus that Cocoa apps get. Add in Cocoa being a bit braindead when you hide
// the app, and we end up having to get our list of windows via XPCOM. Ugh.
// Get the window mediator to do all our lookups.
nsresult rv;
nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, nil);
// Get the frontmost window
nsCOMPtr<nsISimpleEnumerator> orderedWindowList;
rv = wm->GetZOrderXULWindowEnumerator(nsnull, PR_TRUE,
getter_AddRefs(orderedWindowList));
NS_ENSURE_SUCCESS(rv, nil);
PRBool anyWindows = false;
rv = orderedWindowList->HasMoreElements(&anyWindows);
NS_ENSURE_SUCCESS(rv, nil);
nsCOMPtr<nsISupports> frontWindow;
rv = orderedWindowList->GetNext(getter_AddRefs(frontWindow));
NS_ENSURE_SUCCESS(rv, nil);
// Get our list of windows and prepare to iterate. We use this list, ordered
// by window creation date, instead of the z-ordered list because that's what
// native apps do.
nsCOMPtr<nsISimpleEnumerator> windowList;
rv = wm->GetXULWindowEnumerator(nsnull, getter_AddRefs(windowList));
NS_ENSURE_SUCCESS(rv, nil);
// Create the NSMenu that will contain the dock menu items.
NSMenu *menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
[menu setAutoenablesItems:NO];
// Iterate through our list of windows to create our menu
PRBool more;
while (NS_SUCCEEDED(windowList->HasMoreElements(&more)) && more) {
// Get our native window
nsCOMPtr<nsISupports> xulWindow;
rv = windowList->GetNext(getter_AddRefs(xulWindow));
NS_ENSURE_SUCCESS(rv, nil);
NSWindow *cocoaWindow = GetCocoaWindowForXULWindow(xulWindow);
if (!cocoaWindow) continue;
NSString *windowTitle = [cocoaWindow title];
if (!windowTitle) continue;
// Now, create a menu item, and add it to the menu
NSMenuItem *menuItem = [[NSMenuItem alloc]
initWithTitle:windowTitle
action:@selector(dockMenuItemSelected:)
keyEquivalent:@""];
[menuItem setTarget:self];
[menuItem setRepresentedObject:cocoaWindow];
// If this is the foreground window, put a checkmark next to it
if (SameCOMIdentity(xulWindow, frontWindow))
[menuItem setState:NSOnState];
[menu addItem:menuItem];
[menuItem release];
}
// Add application-specific dock menu items. On error, do not insert the
// dock menu items.
nsresult rv;
nsCOMPtr<nsIMacDockSupport> dockSupport = do_GetService("@mozilla.org/widget/macdocksupport;1", &rv);
if (NS_FAILED(rv) || !dockSupport)
return menu;
@ -332,18 +264,6 @@ static NSWindow* GetCocoaWindowForXULWindow(nsISupports *aXULWindow)
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
// One of our dock menu items was selected
- (void)dockMenuItemSelected:(id)sender
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
// Our represented object is an NSWindow
[[sender representedObject] makeKeyAndOrderFront:nil];
[NSApp activateIgnoringOtherApps:YES];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
// If we don't handle applicationShouldTerminate:, a call to [NSApp terminate:]
// (from the browser or from the OS) can result in an unclean shutdown.
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender