1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
/* -*- 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.
*/
#include "MOZIconHelper.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/DocumentInlines.h"
#include "mozilla/widget/NativeMenu.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) {
if (!aContent->IsElement()) {
return false;
}
auto icon = widget::NativeMenu::GetIcon(*aContent->AsElement());
if (!icon) {
return false;
}
mComputedStyle = std::move(icon.mStyle);
mPresContext = aContent->OwnerDoc()->GetPresContext();
if (!mIconLoader) {
mIconLoader = new IconLoader(this);
}
return NS_SUCCEEDED(mIconLoader->LoadIcon(icon.mURI, aContent));
}
//
// 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();
mIconLoader = nullptr;
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
|