mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
31cedc5d17
This also adds a way to set the SVG context for the image as it is rendered outside the DOM Differential Revision: https://phabricator.services.mozilla.com/D223118
181 lines
4.9 KiB
Plaintext
181 lines
4.9 KiB
Plaintext
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/*
|
|
* Retrieves and displays icons in native menu items on Mac OS X.
|
|
*/
|
|
|
|
/* exception_defines.h defines 'try' to 'if (true)' which breaks objective-c
|
|
exceptions and produces errors like: error: unexpected '@' in program'.
|
|
If we define __EXCEPTIONS exception_defines.h will avoid doing this.
|
|
|
|
See bug 666609 for more information.
|
|
|
|
We use <limits> to get the libstdc++ version. */
|
|
#include <limits>
|
|
#if __GLIBCXX__ <= 20070719
|
|
# ifndef __EXCEPTIONS
|
|
# define __EXCEPTIONS
|
|
# endif
|
|
#endif
|
|
|
|
#include "MOZIconHelper.h"
|
|
#include "mozilla/dom/Document.h"
|
|
#include "mozilla/dom/DocumentInlines.h"
|
|
#include "mozilla/SVGImageContext.h"
|
|
#include "nsCocoaUtils.h"
|
|
#include "nsComputedDOMStyle.h"
|
|
#include "nsContentUtils.h"
|
|
#include "nsGkAtoms.h"
|
|
#include "nsIContent.h"
|
|
#include "nsIContentPolicy.h"
|
|
#include "nsMenuItemX.h"
|
|
#include "nsMenuItemIconX.h"
|
|
#include "nsNameSpaceManager.h"
|
|
#include "nsObjCExceptions.h"
|
|
|
|
using namespace mozilla;
|
|
|
|
using mozilla::dom::Element;
|
|
using mozilla::widget::IconLoader;
|
|
|
|
static const uint32_t kIconSize = 16;
|
|
|
|
nsMenuItemIconX::nsMenuItemIconX(Listener* aListener) : mListener(aListener) {
|
|
MOZ_COUNT_CTOR(nsMenuItemIconX);
|
|
}
|
|
|
|
nsMenuItemIconX::~nsMenuItemIconX() {
|
|
if (mIconLoader) {
|
|
mIconLoader->Destroy();
|
|
}
|
|
if (mIconImage) {
|
|
[mIconImage release];
|
|
mIconImage = nil;
|
|
}
|
|
MOZ_COUNT_DTOR(nsMenuItemIconX);
|
|
}
|
|
|
|
void nsMenuItemIconX::SetupIcon(nsIContent* aContent) {
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
bool shouldHaveIcon = StartIconLoad(aContent);
|
|
if (!shouldHaveIcon) {
|
|
// 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.
|
|
if (mIconImage) {
|
|
[mIconImage release];
|
|
mIconImage = nil;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!mIconImage) {
|
|
// Set a placeholder icon, so that the menuitem reserves space for the icon
|
|
// during the load and there is no sudden shift once the icon finishes
|
|
// loading.
|
|
NSSize iconSize = NSMakeSize(kIconSize, kIconSize);
|
|
mIconImage = [[MOZIconHelper placeholderIconWithSize:iconSize] retain];
|
|
}
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
}
|
|
|
|
bool nsMenuItemIconX::StartIconLoad(nsIContent* aContent) {
|
|
RefPtr<nsIURI> iconURI = GetIconURI(aContent);
|
|
if (!iconURI) {
|
|
return false;
|
|
}
|
|
|
|
if (!mIconLoader) {
|
|
mIconLoader = new IconLoader(this);
|
|
}
|
|
|
|
nsresult rv = mIconLoader->LoadIcon(iconURI, aContent);
|
|
return NS_SUCCEEDED(rv);
|
|
}
|
|
|
|
already_AddRefed<nsIURI> nsMenuItemIconX::GetIconURI(nsIContent* aContent) {
|
|
// First, look at the content node's "image" attribute.
|
|
nsAutoString imageURIString;
|
|
bool hasImageAttr =
|
|
aContent->IsElement() &&
|
|
aContent->AsElement()->GetAttr(nsGkAtoms::image, imageURIString);
|
|
|
|
if (hasImageAttr) {
|
|
// Use the URL from the image attribute.
|
|
// If this menu item shouldn't have an icon, the string will be empty,
|
|
// and NS_NewURI will fail.
|
|
RefPtr<nsIURI> iconURI;
|
|
nsresult rv = NS_NewURI(getter_AddRefs(iconURI), imageURIString);
|
|
if (NS_FAILED(rv)) {
|
|
return nullptr;
|
|
}
|
|
return iconURI.forget();
|
|
}
|
|
|
|
// If the content node has no "image" attribute, get the
|
|
// "list-style-image" property from CSS.
|
|
RefPtr<mozilla::dom::Document> document = aContent->GetComposedDoc();
|
|
if (!document || !aContent->IsElement()) {
|
|
return nullptr;
|
|
}
|
|
|
|
RefPtr<const ComputedStyle> sc =
|
|
nsComputedDOMStyle::GetComputedStyle(aContent->AsElement());
|
|
if (!sc) {
|
|
return nullptr;
|
|
}
|
|
|
|
RefPtr<nsIURI> iconURI = sc->StyleList()->GetListStyleImageURI();
|
|
if (!iconURI) {
|
|
return nullptr;
|
|
}
|
|
|
|
mComputedStyle = std::move(sc);
|
|
mPresContext = document->GetPresContext();
|
|
|
|
return iconURI.forget();
|
|
}
|
|
|
|
//
|
|
// mozilla::widget::IconLoader::Listener
|
|
//
|
|
|
|
nsresult nsMenuItemIconX::OnComplete(imgIContainer* aImage) {
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
if (mIconImage) {
|
|
[mIconImage release];
|
|
mIconImage = nil;
|
|
}
|
|
RefPtr<nsPresContext> pc = mPresContext.get();
|
|
UniquePtr<SVGImageContext> svgContext;
|
|
if (pc && mComputedStyle) {
|
|
svgContext = MakeUnique<SVGImageContext>();
|
|
SVGImageContext::MaybeStoreContextPaint(*svgContext, *pc, *mComputedStyle,
|
|
aImage);
|
|
}
|
|
|
|
mIconImage = [[MOZIconHelper
|
|
iconImageFromImageContainer:aImage
|
|
withSize:NSMakeSize(kIconSize, kIconSize)
|
|
svgContext:svgContext.get()
|
|
scaleFactor:0.0f] retain];
|
|
mComputedStyle = nullptr;
|
|
mPresContext = nullptr;
|
|
|
|
if (mListener) {
|
|
mListener->IconUpdated();
|
|
}
|
|
|
|
mIconLoader->Destroy();
|
|
|
|
return NS_OK;
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
}
|