зеркало из https://github.com/mozilla/gecko-dev.git
568 строки
18 KiB
Plaintext
568 строки
18 KiB
Plaintext
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is support for icons in native menu items on Mac OS X.
|
|
*
|
|
* The Initial Developer of the Original Code is Google Inc.
|
|
* Portions created by the Initial Developer are Copyright (C) 2006
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Mark Mentovai <mark@moxienet.com> (Original Author)
|
|
* Josh Aas <josh@mozilla.com>
|
|
* Benjamin Frisch <bfrisch@gmail.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
/*
|
|
* Retrieves and displays icons in native menu items on Mac OS X.
|
|
*/
|
|
|
|
#include "nsMenuItemIconX.h"
|
|
|
|
#include "nsObjCExceptions.h"
|
|
#include "prmem.h"
|
|
#include "nsIContent.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsINameSpaceManager.h"
|
|
#include "nsGkAtoms.h"
|
|
#include "nsIDOMElement.h"
|
|
#include "nsIDOMCSSStyleDeclaration.h"
|
|
#include "nsIDOMCSSValue.h"
|
|
#include "nsIDOMCSSPrimitiveValue.h"
|
|
#include "nsIDOMRect.h"
|
|
#include "nsThreadUtils.h"
|
|
#include "nsToolkit.h"
|
|
#include "nsNetUtil.h"
|
|
#include "imgILoader.h"
|
|
#include "imgIRequest.h"
|
|
#include "nsMenuItemX.h"
|
|
#include "gfxImageSurface.h"
|
|
#include "imgIContainer.h"
|
|
#include "nsCocoaUtils.h"
|
|
|
|
static const PRUint32 kIconWidth = 16;
|
|
static const PRUint32 kIconHeight = 16;
|
|
static const PRUint32 kIconBitsPerComponent = 8;
|
|
static const PRUint32 kIconComponents = 4;
|
|
static const PRUint32 kIconBitsPerPixel = kIconBitsPerComponent *
|
|
kIconComponents;
|
|
static const PRUint32 kIconBytesPerRow = kIconWidth * kIconBitsPerPixel / 8;
|
|
static const PRUint32 kIconBytes = kIconBytesPerRow * kIconHeight;
|
|
|
|
typedef NS_STDCALL_FUNCPROTO(nsresult, GetRectSideMethod, nsIDOMRect,
|
|
GetBottom, (nsIDOMCSSPrimitiveValue**));
|
|
|
|
NS_IMPL_ISUPPORTS2(nsMenuItemIconX, imgIContainerObserver, imgIDecoderObserver)
|
|
|
|
nsMenuItemIconX::nsMenuItemIconX(nsMenuObjectX* aMenuItem,
|
|
nsIContent* aContent,
|
|
NSMenuItem* aNativeMenuItem)
|
|
: mContent(aContent)
|
|
, mMenuObject(aMenuItem)
|
|
, mLoadedIcon(false)
|
|
, mSetIcon(false)
|
|
, mNativeMenuItem(aNativeMenuItem)
|
|
{
|
|
// printf("Creating icon for menu item %d, menu %d, native item is %d\n", aMenuItem, aMenu, aNativeMenuItem);
|
|
}
|
|
|
|
nsMenuItemIconX::~nsMenuItemIconX()
|
|
{
|
|
if (mIconRequest)
|
|
mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
|
}
|
|
|
|
// Called from mMenuObjectX's destructor, to prevent us from outliving it
|
|
// (as might otherwise happen if calls to our imgIDecoderObserver methods
|
|
// are still outstanding). mMenuObjectX owns our nNativeMenuItem.
|
|
void nsMenuItemIconX::Destroy()
|
|
{
|
|
if (mIconRequest) {
|
|
mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
|
mIconRequest = nsnull;
|
|
}
|
|
mMenuObject = nsnull;
|
|
mNativeMenuItem = nil;
|
|
}
|
|
|
|
nsresult
|
|
nsMenuItemIconX::SetupIcon()
|
|
{
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
// Still don't have one, then something is wrong, get out of here.
|
|
if (!mNativeMenuItem) {
|
|
NS_ERROR("No native menu item");
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> iconURI;
|
|
nsresult 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.
|
|
[mNativeMenuItem setImage:nil];
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
rv = LoadIcon(iconURI);
|
|
if (NS_FAILED(rv)) {
|
|
// There is no icon for this menu item, as an error occurred while loading it.
|
|
// An icon might have been set earlier or the place holder icon may have
|
|
// been set. Clear it.
|
|
[mNativeMenuItem setImage:nil];
|
|
}
|
|
return rv;
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
}
|
|
|
|
static PRInt32
|
|
GetDOMRectSide(nsIDOMRect* aRect, GetRectSideMethod aMethod)
|
|
{
|
|
nsCOMPtr<nsIDOMCSSPrimitiveValue> dimensionValue;
|
|
(aRect->*aMethod)(getter_AddRefs(dimensionValue));
|
|
if (!dimensionValue)
|
|
return -1;
|
|
|
|
PRUint16 primitiveType;
|
|
nsresult rv = dimensionValue->GetPrimitiveType(&primitiveType);
|
|
if (NS_FAILED(rv) || primitiveType != nsIDOMCSSPrimitiveValue::CSS_PX)
|
|
return -1;
|
|
|
|
float dimension = 0;
|
|
rv = dimensionValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_PX,
|
|
&dimension);
|
|
if (NS_FAILED(rv))
|
|
return -1;
|
|
|
|
return NSToIntRound(dimension);
|
|
}
|
|
|
|
nsresult
|
|
nsMenuItemIconX::GetIconURI(nsIURI** aIconURI)
|
|
{
|
|
if (!mMenuObject)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// Mac native menu items support having both a checkmark and an icon
|
|
// simultaneously, but this is unheard of in the cross-platform toolkit,
|
|
// seemingly because the win32 theme is unable to cope with both at once.
|
|
// The downside is that it's possible to get a menu item marked with a
|
|
// native checkmark and a checkmark for an icon. Head off that possibility
|
|
// by pretending that no icon exists if this is a checkable menu item.
|
|
if (mMenuObject->MenuObjectType() == eMenuItemObjectType) {
|
|
nsMenuItemX* menuItem = static_cast<nsMenuItemX*>(mMenuObject);
|
|
if (menuItem->GetMenuItemType() != eRegularMenuItemType)
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
if (!mContent)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// First, look at the content node's "image" attribute.
|
|
nsAutoString imageURIString;
|
|
bool hasImageAttr = mContent->GetAttr(kNameSpaceID_None,
|
|
nsGkAtoms::image,
|
|
imageURIString);
|
|
|
|
nsresult rv;
|
|
nsCOMPtr<nsIDOMCSSValue> cssValue;
|
|
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssStyleDecl;
|
|
nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
|
|
PRUint16 primitiveType;
|
|
if (!hasImageAttr) {
|
|
// If the content node has no "image" attribute, get the
|
|
// "list-style-image" property from CSS.
|
|
nsCOMPtr<nsIDOMDocument> domDocument =
|
|
do_QueryInterface(mContent->GetDocument());
|
|
if (!domDocument)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIDOMWindow> window;
|
|
rv = domDocument->GetDefaultView(getter_AddRefs(window));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
if (!window)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mContent);
|
|
if (!domElement)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
rv = window->GetComputedStyle(domElement, EmptyString(),
|
|
getter_AddRefs(cssStyleDecl));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
NS_NAMED_LITERAL_STRING(listStyleImage, "list-style-image");
|
|
rv = cssStyleDecl->GetPropertyCSSValue(listStyleImage,
|
|
getter_AddRefs(cssValue));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
primitiveValue = do_QueryInterface(cssValue);
|
|
if (!primitiveValue) return NS_ERROR_FAILURE;
|
|
|
|
rv = primitiveValue->GetPrimitiveType(&primitiveType);
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (primitiveType != nsIDOMCSSPrimitiveValue::CSS_URI)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
rv = primitiveValue->GetStringValue(imageURIString);
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
// Empty the mImageRegionRect initially as the image region CSS could
|
|
// have been changed and now have an error or have been removed since the
|
|
// last GetIconURI call.
|
|
mImageRegionRect.SetEmpty();
|
|
|
|
// If this menu item shouldn't have an icon, the string will be empty,
|
|
// and NS_NewURI will fail.
|
|
nsCOMPtr<nsIURI> iconURI;
|
|
rv = NS_NewURI(getter_AddRefs(iconURI), imageURIString);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
*aIconURI = iconURI;
|
|
NS_ADDREF(*aIconURI);
|
|
|
|
if (!hasImageAttr) {
|
|
// Check if the icon has a specified image region so that it can be
|
|
// cropped appropriately before being displayed.
|
|
NS_NAMED_LITERAL_STRING(imageRegion, "-moz-image-region");
|
|
rv = cssStyleDecl->GetPropertyCSSValue(imageRegion,
|
|
getter_AddRefs(cssValue));
|
|
// Just return NS_OK if there if there is a failure due to no
|
|
// moz-image region specified so the whole icon will be drawn anyway.
|
|
if (NS_FAILED(rv)) return NS_OK;
|
|
|
|
primitiveValue = do_QueryInterface(cssValue);
|
|
if (!primitiveValue) return NS_OK;
|
|
|
|
rv = primitiveValue->GetPrimitiveType(&primitiveType);
|
|
if (NS_FAILED(rv)) return NS_OK;
|
|
if (primitiveType != nsIDOMCSSPrimitiveValue::CSS_RECT)
|
|
return NS_OK;
|
|
|
|
nsCOMPtr<nsIDOMRect> imageRegionRect;
|
|
rv = primitiveValue->GetRectValue(getter_AddRefs(imageRegionRect));
|
|
if (NS_FAILED(rv)) return NS_OK;
|
|
|
|
if (imageRegionRect) {
|
|
// Return NS_ERROR_FAILURE if the image region is invalid so the image
|
|
// is not drawn, and behavior is similar to XUL menus.
|
|
PRInt32 bottom = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetBottom);
|
|
PRInt32 right = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetRight);
|
|
PRInt32 top = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetTop);
|
|
PRInt32 left = GetDOMRectSide(imageRegionRect, &nsIDOMRect::GetLeft);
|
|
|
|
if (top < 0 || left < 0 || bottom <= top || right <= left)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
mImageRegionRect.SetRect(left, top, right - left, bottom - top);
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
|
|
{
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
if (mIconRequest) {
|
|
// Another icon request is already in flight. Kill it.
|
|
mIconRequest->Cancel(NS_BINDING_ABORTED);
|
|
mIconRequest = nsnull;
|
|
}
|
|
|
|
mLoadedIcon = false;
|
|
|
|
if (!mContent) return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<nsIDocument> document = mContent->OwnerDoc();
|
|
|
|
nsCOMPtr<nsILoadGroup> loadGroup = document->GetDocumentLoadGroup();
|
|
if (!loadGroup) return NS_ERROR_FAILURE;
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
nsCOMPtr<imgILoader> loader = do_GetService("@mozilla.org/image/loader;1",
|
|
&rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (!mSetIcon) {
|
|
// Set a completely transparent 16x16 image as the icon on this menu item
|
|
// as a placeholder. This keeps the menu item text displayed in the same
|
|
// position that it will be displayed when the real icon is loaded, and
|
|
// prevents it from jumping around or looking misaligned.
|
|
|
|
static bool sInitializedPlaceholder;
|
|
static NSImage* sPlaceholderIconImage;
|
|
if (!sInitializedPlaceholder) {
|
|
sInitializedPlaceholder = true;
|
|
|
|
// 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;
|
|
|
|
if (mNativeMenuItem)
|
|
[mNativeMenuItem setImage:sPlaceholderIconImage];
|
|
}
|
|
|
|
// Passing in null for channelPolicy here since nsMenuItemIconX::LoadIcon is
|
|
// not exposed to web content
|
|
rv = loader->LoadImage(aIconURI, nsnull, nsnull, nsnull, loadGroup, this,
|
|
nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull,
|
|
nsnull, getter_AddRefs(mIconRequest));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// We need to request the icon be decoded (bug 573583, bug 705516).
|
|
mIconRequest->RequestDecode();
|
|
|
|
return NS_OK;
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
}
|
|
|
|
//
|
|
// imgIContainerObserver
|
|
//
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::FrameChanged(imgIRequest* aRequest,
|
|
imgIContainer* aContainer,
|
|
const nsIntRect* aDirtyRect)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
//
|
|
// imgIDecoderObserver
|
|
//
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::OnStartRequest(imgIRequest* aRequest)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::OnStartDecode(imgIRequest* aRequest)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::OnStartContainer(imgIRequest* aRequest,
|
|
imgIContainer* aContainer)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::OnStartFrame(imgIRequest* aRequest, PRUint32 aFrame)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::OnDataAvailable(imgIRequest* aRequest,
|
|
bool aCurrentFrame,
|
|
const nsIntRect* aRect)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::OnStopFrame(imgIRequest* aRequest,
|
|
PRUint32 aFrame)
|
|
{
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
if (aRequest != mIconRequest)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// Only support one frame.
|
|
if (mLoadedIcon)
|
|
return NS_OK;
|
|
|
|
if (!mNativeMenuItem)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
nsCOMPtr<imgIContainer> imageContainer;
|
|
aRequest->GetImage(getter_AddRefs(imageContainer));
|
|
if (!imageContainer) {
|
|
[mNativeMenuItem setImage:nil];
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
PRInt32 origWidth = 0, origHeight = 0;
|
|
imageContainer->GetWidth(&origWidth);
|
|
imageContainer->GetHeight(&origHeight);
|
|
|
|
// If the image region is invalid, don't draw the image to almost match
|
|
// the behavior of other platforms.
|
|
if (!mImageRegionRect.IsEmpty() &&
|
|
(mImageRegionRect.XMost() > origWidth ||
|
|
mImageRegionRect.YMost() > origHeight)) {
|
|
[mNativeMenuItem setImage:nil];
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
if (mImageRegionRect.IsEmpty()) {
|
|
mImageRegionRect.SetRect(0, 0, origWidth, origHeight);
|
|
}
|
|
|
|
nsRefPtr<gfxImageSurface> frame;
|
|
nsresult rv = imageContainer->CopyFrame( imgIContainer::FRAME_CURRENT,
|
|
imgIContainer::FLAG_NONE,
|
|
getter_AddRefs(frame));
|
|
if (NS_FAILED(rv) || !frame) {
|
|
[mNativeMenuItem setImage:nil];
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
CGImageRef origImage = NULL;
|
|
rv = nsCocoaUtils::CreateCGImageFromSurface(frame, &origImage);
|
|
if (NS_FAILED(rv) || !origImage) {
|
|
[mNativeMenuItem setImage:nil];
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
bool createSubImage = !(mImageRegionRect.x == 0 && mImageRegionRect.y == 0 &&
|
|
mImageRegionRect.width == origWidth && mImageRegionRect.height == origHeight);
|
|
|
|
CGImageRef finalImage = NULL;
|
|
if (createSubImage) {
|
|
// if mImageRegionRect is set using CSS, we need to slice a piece out of the overall
|
|
// image to use as the icon
|
|
finalImage = ::CGImageCreateWithImageInRect(origImage,
|
|
::CGRectMake(mImageRegionRect.x,
|
|
mImageRegionRect.y,
|
|
mImageRegionRect.width,
|
|
mImageRegionRect.height));
|
|
::CGImageRelease(origImage);
|
|
if (!finalImage) {
|
|
[mNativeMenuItem setImage:nil];
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
} else {
|
|
finalImage = origImage;
|
|
}
|
|
// The image may not be the right size for a menu icon (16x16).
|
|
// Create a new CGImage for the menu item.
|
|
PRUint8* bitmap = (PRUint8*)malloc(kIconBytes);
|
|
|
|
CGColorSpaceRef colorSpace = ::CGColorSpaceCreateDeviceRGB();
|
|
|
|
CGContextRef bitmapContext = ::CGBitmapContextCreate(bitmap, kIconWidth, kIconHeight,
|
|
kIconBitsPerComponent,
|
|
kIconBytesPerRow,
|
|
colorSpace,
|
|
kCGImageAlphaPremultipliedLast);
|
|
::CGColorSpaceRelease(colorSpace);
|
|
if (!bitmapContext) {
|
|
::CGImageRelease(finalImage);
|
|
free(bitmap);
|
|
::CGColorSpaceRelease(colorSpace);
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
CGRect iconRect = ::CGRectMake(0, 0, kIconWidth, kIconHeight);
|
|
::CGContextClearRect(bitmapContext, iconRect);
|
|
::CGContextDrawImage(bitmapContext, iconRect, finalImage);
|
|
|
|
CGImageRef iconImage = ::CGBitmapContextCreateImage(bitmapContext);
|
|
|
|
::CGImageRelease(finalImage);
|
|
::CGContextRelease(bitmapContext);
|
|
free(bitmap);
|
|
|
|
if (!iconImage) return NS_ERROR_FAILURE;
|
|
|
|
NSImage *newImage = nil;
|
|
rv = nsCocoaUtils::CreateNSImageFromCGImage(iconImage, &newImage);
|
|
if (NS_FAILED(rv) || !newImage) {
|
|
[mNativeMenuItem setImage:nil];
|
|
::CGImageRelease(iconImage);
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
[mNativeMenuItem setImage:newImage];
|
|
|
|
[newImage release];
|
|
::CGImageRelease(iconImage);
|
|
|
|
mLoadedIcon = true;
|
|
mSetIcon = true;
|
|
|
|
return NS_OK;
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::OnStopContainer(imgIRequest* aRequest,
|
|
imgIContainer* aContainer)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::OnStopDecode(imgIRequest* aRequest,
|
|
nsresult status,
|
|
const PRUnichar* statusArg)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::OnStopRequest(imgIRequest* aRequest,
|
|
bool aIsLastPart)
|
|
{
|
|
if (mIconRequest && mIconRequest == aRequest) {
|
|
mIconRequest->Cancel(NS_BINDING_ABORTED);
|
|
mIconRequest = nsnull;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::OnDiscard(imgIRequest* aRequest)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsMenuItemIconX::OnImageIsAnimated(imgIRequest* aRequest)
|
|
{
|
|
return NS_OK;
|
|
}
|