Favicons not showing up in history menu (most of the time). Patch by Stan Shebs. b=379660 r=josh sr=pav

This commit is contained in:
joshmoz@gmail.com 2007-08-02 12:08:40 -07:00
Родитель eef7bc4c09
Коммит b294a2e73e
5 изменённых файлов: 68 добавлений и 59 удалений

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

@ -54,6 +54,7 @@ class imgIRequest;
class nsIMenu;
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
class nsMenuItemIconX : public imgIDecoderObserver
@ -61,7 +62,8 @@ class nsMenuItemIconX : public imgIDecoderObserver
public:
nsMenuItemIconX(nsISupports* aMenuItem,
nsIMenu* aMenu,
nsIContent* aContent);
nsIContent* aContent,
NSMenuItem* aNativeMenuItem);
private:
~nsMenuItemIconX();
@ -94,6 +96,7 @@ protected:
PRUint16 mMenuItemIndex;
PRPackedBool mLoadedIcon;
PRPackedBool mSetIcon;
NSMenuItem* mNativeMenuItem;
};
#endif // nsMenuItemIconX_h_

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

@ -63,6 +63,7 @@
#include "imgIRequest.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
#include "nsMenuX.h"
static const PRUint32 kIconWidth = 16;
@ -85,7 +86,8 @@ NS_IMPL_ISUPPORTS2(nsMenuItemIconX, imgIContainerObserver, imgIDecoderObserver)
nsMenuItemIconX::nsMenuItemIconX(nsISupports* aMenuItem,
nsIMenu* aMenu,
nsIContent* aContent)
nsIContent* aContent,
NSMenuItem* aNativeMenuItem)
: mContent(aContent)
, mMenuItem(aMenuItem)
, mMenu(aMenu)
@ -93,7 +95,9 @@ nsMenuItemIconX::nsMenuItemIconX(nsISupports* aMenuItem,
, mMenuItemIndex(0)
, mLoadedIcon(PR_FALSE)
, mSetIcon(PR_FALSE)
, mNativeMenuItem(aNativeMenuItem)
{
// printf("Creating icon for menu item %d, menu %d, native item is %d\n", aMenuItem, aMenu, aNativeMenuItem);
}
@ -119,14 +123,23 @@ nsMenuItemIconX::SetupIcon()
if (NS_FAILED(rv)) return rv;
}
// If our native menu item isn't filled in, it's because this icon is for
// a submenu that wasn't given its native menu item until later.
if (!mNativeMenuItem)
mNativeMenuItem = (static_cast<nsMenuX*>(mMenu))->GetNativeMenuItem();
// Still don't have one, then something is wrong, get out of here.
if (!mNativeMenuItem) {
NS_ERROR("No native menu item\n");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIURI> iconURI;
rv = GetIconURI(getter_AddRefs(iconURI));
if (NS_FAILED(rv)) {
// There is no icon for this menu item. An icon might have been set
// earlier. Clear it.
OSStatus err;
err = ::SetMenuItemIconHandle(mMenuRef, mMenuItemIndex, kMenuNoIcon, NULL);
if (err != noErr) return NS_ERROR_FAILURE;
[mNativeMenuItem setImage:nil];
return NS_OK;
}
@ -248,54 +261,18 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
// prevents it from jumping around or looking misaligned.
static PRBool sInitializedPlaceholder;
static CGImageRef sPlaceholderIconImage;
static NSImage* sPlaceholderIconImage;
if (!sInitializedPlaceholder) {
sInitializedPlaceholder = PR_TRUE;
PRUint8* bitmap = (PRUint8*)malloc(kIconBytes);
CGColorSpaceRef colorSpace = ::CGColorSpaceCreateDeviceRGB();
CGContextRef bitmapContext;
bitmapContext = ::CGBitmapContextCreate(bitmap, kIconWidth, kIconHeight,
kIconBitsPerComponent,
kIconBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedFirst);
if (!bitmapContext) {
free(bitmap);
::CGColorSpaceRelease(colorSpace);
return NS_ERROR_FAILURE;
}
CGRect iconRect = ::CGRectMake(0, 0, kIconWidth, kIconHeight);
::CGContextClearRect(bitmapContext, iconRect);
::CGContextRelease(bitmapContext);
CGDataProviderRef provider;
provider = ::CGDataProviderCreateWithData(NULL, bitmap, kIconBytes,
PRAllocCGFree);
if (!provider) {
free(bitmap);
::CGColorSpaceRelease(colorSpace);
return NS_ERROR_FAILURE;
}
sPlaceholderIconImage =
::CGImageCreate(kIconWidth, kIconHeight, kIconBitsPerComponent,
kIconBitsPerPixel, kIconBytesPerRow, colorSpace,
kCGImageAlphaPremultipliedFirst, provider, NULL, TRUE,
kCGRenderingIntentDefault);
::CGColorSpaceRelease(colorSpace);
::CGDataProviderRelease(provider);
// Note that we only create the one and reuse it forever, so this is not a leak.
sPlaceholderIconImage = [[NSImage alloc] initWithSize:NSMakeSize(kIconWidth, kIconHeight)];
}
if (!sPlaceholderIconImage) return NS_ERROR_FAILURE;
OSStatus err;
err = ::SetMenuItemIconHandle(mMenuRef, mMenuItemIndex, kMenuCGImageRefType,
(Handle)sPlaceholderIconImage);
if (err != noErr) return NS_ERROR_FAILURE;
if (mNativeMenuItem)
[mNativeMenuItem setImage:sPlaceholderIconImage];
}
rv = loader->LoadImage(aIconURI, nsnull, nsnull, loadGroup, this,
@ -541,11 +518,30 @@ nsMenuItemIconX::OnStopFrame(imgIRequest* aRequest,
::CGDataProviderRelease(provider);
if (!iconImage) return NS_ERROR_FAILURE;
OSStatus err;
err = ::SetMenuItemIconHandle(mMenuRef, mMenuItemIndex, kMenuCGImageRefType,
(Handle)iconImage);
NSRect imageRect = NSMakeRect(0.0, 0.0, 0.0, 0.0);
CGContextRef imageContext = nil;
// Get the image dimensions.
imageRect.size.width = kIconWidth;
imageRect.size.height = kIconHeight;
// Create a new image to receive the Quartz image data.
NSImage* newImage = [[NSImage alloc] initWithSize:imageRect.size];
[newImage lockFocus];
// Get the Quartz context and draw.
imageContext = (CGContextRef)[[NSGraphicsContext currentContext]
graphicsPort];
CGContextDrawImage(imageContext, *(CGRect*)&imageRect, iconImage);
[newImage unlockFocus];
if (!mNativeMenuItem) return NS_ERROR_FAILURE;
[mNativeMenuItem setImage:newImage];
[newImage release];
::CGImageRelease(iconImage);
if (err != noErr) return NS_ERROR_FAILURE;
mLoadedIcon = PR_TRUE;
mSetIcon = PR_TRUE;

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

@ -143,7 +143,7 @@ NS_METHOD nsMenuItemX::Create(nsIMenu* aParent, const nsString & aLabel, PRBool
[mNativeMenuItem setEnabled:(BOOL)mEnabled];
}
mIcon = new nsMenuItemIconX(static_cast<nsIMenuItem*>(this), mMenuParent, mContent);
mIcon = new nsMenuItemIconX(static_cast<nsIMenuItem*>(this), mMenuParent, mContent, mNativeMenuItem);
return NS_OK;
}

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

@ -82,6 +82,8 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSICHANGEOBSERVER
id GetNativeMenuItem();
// nsIMenuListener methods
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
@ -160,6 +162,7 @@ protected:
PRInt16 mMacMenuID;
NSMenu* mMacMenu; // strong ref, we own it
MenuDelegate* mMenuDelegate; // strong ref, we keep this around to get events for us
NSMenuItem* mNativeMenuItem; // strong ref, we own
PRPackedBool mIsEnabled;
PRPackedBool mDestroyHandlerCalled;
PRPackedBool mNeedsRebuild;

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

@ -106,7 +106,7 @@ NS_IMPL_ISUPPORTS4(nsMenuX, nsIMenu, nsIMenuListener, nsIChangeObserver, nsISupp
nsMenuX::nsMenuX()
: mParent(nsnull), mManager(nsnull), mMacMenuID(0), mMacMenu(nil),
: mParent(nsnull), mManager(nsnull), mMacMenuID(0), mMacMenu(nil), mNativeMenuItem(nil),
mIsEnabled(PR_TRUE), mDestroyHandlerCalled(PR_FALSE),
mNeedsRebuild(PR_TRUE), mConstructed(PR_FALSE), mVisible(PR_TRUE),
mXBLAttached(PR_FALSE)
@ -124,6 +124,7 @@ nsMenuX::~nsMenuX()
[mMacMenu release];
[mMenuDelegate release];
[mNativeMenuItem release];
// alert the change notifier we don't care no more
mManager->Unregister(mMenuContent);
@ -168,7 +169,7 @@ nsMenuX::Create(nsISupports * aParent, const nsAString &aLabel, const nsAString
MenuConstruct(fake, nsnull, nsnull, nsnull);
if (menu)
mIcon = new nsMenuItemIconX(static_cast<nsIMenu*>(this), menu, mMenuContent);
mIcon = new nsMenuItemIconX(static_cast<nsIMenu*>(this), menu, mMenuContent, nsnull);
return NS_OK;
}
@ -296,15 +297,14 @@ nsresult nsMenuX::AddMenu(nsIMenu * aMenu)
PRBool enabled;
aMenu->GetEnabled(&enabled);
NSString *newCocoaLabelString = MenuHelpersX::CreateTruncatedCocoaLabel(label);
NSMenuItem* newNativeMenuItem = [[NSMenuItem alloc] initWithTitle:newCocoaLabelString action:nil keyEquivalent:@""];
[newNativeMenuItem setEnabled:enabled];
[mMacMenu addItem:newNativeMenuItem];
mNativeMenuItem = [[NSMenuItem alloc] initWithTitle:newCocoaLabelString action:nil keyEquivalent:@""];
[mNativeMenuItem setEnabled:enabled];
[mMacMenu addItem:mNativeMenuItem];
[newCocoaLabelString release];
[newNativeMenuItem release];
NSMenu* childMenu;
if (aMenu->GetNativeData((void**)&childMenu) == NS_OK)
[newNativeMenuItem setSubmenu:childMenu];
[mNativeMenuItem setSubmenu:childMenu];
return NS_OK;
}
@ -541,7 +541,7 @@ nsEventStatus nsMenuX::MenuConstruct(
gConstructingMenu = PR_FALSE;
mNeedsRebuild = PR_FALSE;
// printf("Done building, mMenuItemVoidArray.Count() = %d \n", mMenuItemVoidArray.Count());
// printf("Done building, mMenuItemsArray.Count() = %d \n", mMenuItemsArray.Count());
return nsEventStatus_eIgnore;
}
@ -1031,6 +1031,13 @@ nsMenuX::GetMenuRefAndItemIndexForMenuItem(nsISupports* aMenuItem,
}
id
nsMenuX::GetNativeMenuItem()
{
return mNativeMenuItem;
}
//
// nsIChangeObserver
//