mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
Bug 1920468: Support badging the dock icon with an arbritrary image. r=spohl,jwatt
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
This commit is contained in:
parent
7f989caf84
commit
31cedc5d17
@ -23,6 +23,7 @@ XPIDL_SOURCES += [
|
||||
"nsILayoutHistoryState.idl",
|
||||
"nsIPreloadedStyleSheet.idl",
|
||||
"nsIStyleSheetService.idl",
|
||||
"nsISVGPaintContext.idl",
|
||||
]
|
||||
|
||||
if CONFIG["MOZ_DEBUG"]:
|
||||
|
35
layout/base/nsISVGPaintContext.idl
Normal file
35
layout/base/nsISVGPaintContext.idl
Normal file
@ -0,0 +1,35 @@
|
||||
/* -*- Mode: IDL; 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/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/*
|
||||
* Used to set SVG context values when rendering SVG images outside of a DOM
|
||||
* context.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(43966236-3146-4518-ab39-f938795cd1a1)]
|
||||
interface nsISVGPaintContext : nsISupports
|
||||
{
|
||||
/**
|
||||
* The fill color to use. Any CSS color value.
|
||||
*/
|
||||
readonly attribute ACString fillColor;
|
||||
|
||||
/**
|
||||
* The stroke color to use. Any CSS color value.
|
||||
*/
|
||||
readonly attribute ACString strokeColor;
|
||||
|
||||
/**
|
||||
* The fill opacity to use.
|
||||
*/
|
||||
readonly attribute float fillOpacity;
|
||||
|
||||
/**
|
||||
* The stroke opacity to use.
|
||||
*/
|
||||
readonly attribute float strokeOpacity;
|
||||
};
|
@ -15,6 +15,8 @@
|
||||
#include "nsIFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsStyleStruct.h"
|
||||
#include "nsISVGPaintContext.h"
|
||||
#include "mozilla/ServoCSSParser.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -85,4 +87,50 @@ void SVGImageContext::MaybeStoreContextPaint(SVGImageContext& aContext,
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void SVGImageContext::MaybeStoreContextPaint(SVGImageContext& aContext,
|
||||
nsISVGPaintContext* aPaintContext,
|
||||
imgIContainer* aImgContainer) {
|
||||
if (aImgContainer->GetType() != imgIContainer::TYPE_VECTOR ||
|
||||
!aPaintContext) {
|
||||
// Avoid this overhead for raster images.
|
||||
return;
|
||||
}
|
||||
|
||||
bool haveContextPaint = false;
|
||||
auto contextPaint = MakeRefPtr<SVGEmbeddingContextPaint>();
|
||||
nsCString value;
|
||||
float opacity;
|
||||
|
||||
if (NS_SUCCEEDED(aPaintContext->GetStrokeColor(value)) && !value.IsEmpty()) {
|
||||
nscolor color;
|
||||
if (ServoCSSParser::ComputeColor(nullptr, NS_RGB(0, 0, 0), value, &color)) {
|
||||
haveContextPaint = true;
|
||||
contextPaint->SetStroke(color);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(aPaintContext->GetFillColor(value)) && !value.IsEmpty()) {
|
||||
nscolor color;
|
||||
if (ServoCSSParser::ComputeColor(nullptr, NS_RGB(0, 0, 0), value, &color)) {
|
||||
haveContextPaint = true;
|
||||
contextPaint->SetFill(color);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(aPaintContext->GetStrokeOpacity(&opacity))) {
|
||||
haveContextPaint = true;
|
||||
contextPaint->SetStrokeOpacity(opacity);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(aPaintContext->GetFillOpacity(&opacity))) {
|
||||
haveContextPaint = true;
|
||||
contextPaint->SetFillOpacity(opacity);
|
||||
}
|
||||
|
||||
if (haveContextPaint) {
|
||||
aContext.mContextPaint = std::move(contextPaint);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "Units.h"
|
||||
|
||||
class nsIFrame;
|
||||
class nsISVGPaintContext;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -60,6 +61,10 @@ class SVGImageContext {
|
||||
const nsPresContext&, const ComputedStyle&,
|
||||
imgIContainer*);
|
||||
|
||||
static void MaybeStoreContextPaint(SVGImageContext& aContext,
|
||||
nsISVGPaintContext* aPaintContext,
|
||||
imgIContainer* aImgContainer);
|
||||
|
||||
const Maybe<CSSIntSize>& GetViewportSize() const { return mViewportSize; }
|
||||
|
||||
void SetViewportSize(const Maybe<CSSIntSize>& aSize) {
|
||||
|
@ -15,7 +15,8 @@ class nsPresContext;
|
||||
|
||||
namespace mozilla {
|
||||
class ComputedStyle;
|
||||
}
|
||||
class SVGImageContext;
|
||||
} // namespace mozilla
|
||||
|
||||
@interface MOZIconHelper : NSObject
|
||||
|
||||
@ -25,9 +26,8 @@ class ComputedStyle;
|
||||
// Returns an autoreleased NSImage.
|
||||
+ (NSImage*)iconImageFromImageContainer:(imgIContainer*)aImage
|
||||
withSize:(NSSize)aSize
|
||||
presContext:(const nsPresContext*)aPresContext
|
||||
computedStyle:
|
||||
(const mozilla::ComputedStyle*)aComputedStyle
|
||||
svgContext:
|
||||
(const mozilla::SVGImageContext*)aSVGContext
|
||||
scaleFactor:(CGFloat)aScaleFactor;
|
||||
|
||||
@end
|
||||
|
@ -22,21 +22,20 @@
|
||||
// Returns an autoreleased NSImage.
|
||||
+ (NSImage*)iconImageFromImageContainer:(imgIContainer*)aImage
|
||||
withSize:(NSSize)aSize
|
||||
presContext:(const nsPresContext*)aPresContext
|
||||
computedStyle:
|
||||
(const mozilla::ComputedStyle*)aComputedStyle
|
||||
svgContext:
|
||||
(const mozilla::SVGImageContext*)aSVGContext
|
||||
scaleFactor:(CGFloat)aScaleFactor {
|
||||
bool isEntirelyBlack = false;
|
||||
NSImage* retainedImage = nil;
|
||||
nsresult rv;
|
||||
if (aScaleFactor != 0.0f) {
|
||||
rv = nsCocoaUtils::CreateNSImageFromImageContainer(
|
||||
aImage, imgIContainer::FRAME_CURRENT, aPresContext, aComputedStyle,
|
||||
aSize, &retainedImage, aScaleFactor, &isEntirelyBlack);
|
||||
aImage, imgIContainer::FRAME_CURRENT, aSVGContext, aSize,
|
||||
&retainedImage, aScaleFactor, &isEntirelyBlack);
|
||||
} else {
|
||||
rv = nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer(
|
||||
aImage, imgIContainer::FRAME_CURRENT, aPresContext, aComputedStyle,
|
||||
aSize, &retainedImage, &isEntirelyBlack);
|
||||
aImage, imgIContainer::FRAME_CURRENT, aSVGContext, aSize,
|
||||
&retainedImage, &isEntirelyBlack);
|
||||
}
|
||||
|
||||
NSImage* image = [retainedImage autorelease];
|
||||
|
@ -547,7 +547,7 @@ OSXNotificationCenter::OnImageReady(nsISupports* aUserData,
|
||||
// properties.
|
||||
// TODO: Do we have a reasonable size to pass around here?
|
||||
nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer(
|
||||
image, imgIContainer::FRAME_FIRST, nullptr, nullptr, NSMakeSize(0, 0),
|
||||
image, imgIContainer::FRAME_FIRST, nullptr, NSMakeSize(0, 0),
|
||||
&cocoaImage);
|
||||
(osxni->mPendingNotification).contentImage = cocoaImage;
|
||||
[cocoaImage release];
|
||||
|
@ -286,8 +286,8 @@ class nsCocoaUtils {
|
||||
the <code>NSImage</code>.
|
||||
@param aImage the image to extract a frame from
|
||||
@param aWhichFrame the frame to extract (see imgIContainer FRAME_*)
|
||||
@param aComputedStyle the ComputedStyle of the element that the image is
|
||||
for, to support SVG context paint properties, can be null
|
||||
@param aSVGContext the SVG context paint properties for the image. Can be
|
||||
null.
|
||||
@param aResult the resulting NSImage
|
||||
@param scaleFactor the desired scale factor of the NSImage (2 for a retina
|
||||
display)
|
||||
@ -298,18 +298,16 @@ class nsCocoaUtils {
|
||||
*/
|
||||
static nsresult CreateNSImageFromImageContainer(
|
||||
imgIContainer* aImage, uint32_t aWhichFrame,
|
||||
const nsPresContext* aPresContext,
|
||||
const mozilla::ComputedStyle* aComputedStyle,
|
||||
const NSSize& aPreferredSize, NSImage** aResult, CGFloat scaleFactor,
|
||||
bool* aIsEntirelyBlack = nullptr);
|
||||
const mozilla::SVGImageContext* aSVGContext, const NSSize& aPreferredSize,
|
||||
NSImage** aResult, CGFloat scaleFactor, bool* aIsEntirelyBlack = nullptr);
|
||||
|
||||
/** Creates a Cocoa <code>NSImage</code> from a frame of an
|
||||
<code>imgIContainer</code>. The new <code>NSImage</code> will have both a
|
||||
regular and HiDPI representation. The caller owns the <code>NSImage</code>.
|
||||
@param aImage the image to extract a frame from
|
||||
@param aWhichFrame the frame to extract (see imgIContainer FRAME_*)
|
||||
@param aComputedStyle the ComputedStyle of the element that the image is
|
||||
for, to support SVG context paint properties, can be null
|
||||
@param aSVGContext the SVG context paint properties for the image. Can be
|
||||
null.
|
||||
@param aResult the resulting NSImage
|
||||
@param aIsEntirelyBlack an outparam that, if non-null, will be set to a
|
||||
bool that indicates whether the RGB values on all
|
||||
@ -318,10 +316,8 @@ class nsCocoaUtils {
|
||||
*/
|
||||
static nsresult CreateDualRepresentationNSImageFromImageContainer(
|
||||
imgIContainer* aImage, uint32_t aWhichFrame,
|
||||
const nsPresContext* aPresContext,
|
||||
const mozilla::ComputedStyle* aComputedStyle,
|
||||
const NSSize& aPreferredSize, NSImage** aResult,
|
||||
bool* aIsEntirelyBlack = nullptr);
|
||||
const mozilla::SVGImageContext* aSVGContext, const NSSize& aPreferredSize,
|
||||
NSImage** aResult, bool* aIsEntirelyBlack = nullptr);
|
||||
|
||||
/**
|
||||
* Returns nsAString for aSrc.
|
||||
|
@ -506,9 +506,8 @@ nsresult nsCocoaUtils::CreateNSImageFromCGImage(CGImageRef aInputImage,
|
||||
|
||||
nsresult nsCocoaUtils::CreateNSImageFromImageContainer(
|
||||
imgIContainer* aImage, uint32_t aWhichFrame,
|
||||
const nsPresContext* aPresContext, const ComputedStyle* aComputedStyle,
|
||||
const NSSize& aPreferredSize, NSImage** aResult, CGFloat scaleFactor,
|
||||
bool* aIsEntirelyBlack) {
|
||||
const SVGImageContext* aSVGContext, const NSSize& aPreferredSize,
|
||||
NSImage** aResult, CGFloat scaleFactor, bool* aIsEntirelyBlack) {
|
||||
RefPtr<SourceSurface> surface;
|
||||
int32_t width = 0;
|
||||
int32_t height = 0;
|
||||
@ -544,14 +543,15 @@ nsresult nsCocoaUtils::CreateNSImageFromImageContainer(
|
||||
|
||||
gfxContext context(drawTarget);
|
||||
|
||||
SVGImageContext svgContext;
|
||||
if (aPresContext && aComputedStyle) {
|
||||
SVGImageContext::MaybeStoreContextPaint(svgContext, *aPresContext,
|
||||
*aComputedStyle, aImage);
|
||||
UniquePtr<SVGImageContext> svgContext;
|
||||
if (!aSVGContext) {
|
||||
svgContext = MakeUnique<SVGImageContext>();
|
||||
aSVGContext = svgContext.get();
|
||||
}
|
||||
|
||||
mozilla::image::ImgDrawResult res =
|
||||
aImage->Draw(&context, scaledSize, ImageRegion::Create(scaledSize),
|
||||
aWhichFrame, SamplingFilter::POINT, svgContext,
|
||||
aWhichFrame, SamplingFilter::POINT, *aSVGContext,
|
||||
imgIContainer::FLAG_SYNC_DECODE, 1.0);
|
||||
|
||||
if (res != mozilla::image::ImgDrawResult::SUCCESS) {
|
||||
@ -589,12 +589,12 @@ nsresult nsCocoaUtils::CreateNSImageFromImageContainer(
|
||||
|
||||
nsresult nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer(
|
||||
imgIContainer* aImage, uint32_t aWhichFrame,
|
||||
const nsPresContext* aPresContext, const ComputedStyle* aComputedStyle,
|
||||
const NSSize& aPreferredSize, NSImage** aResult, bool* aIsEntirelyBlack) {
|
||||
const SVGImageContext* aSVGContext, const NSSize& aPreferredSize,
|
||||
NSImage** aResult, bool* aIsEntirelyBlack) {
|
||||
NSImage* newRepresentation = nil;
|
||||
nsresult rv = CreateNSImageFromImageContainer(
|
||||
aImage, aWhichFrame, aPresContext, aComputedStyle, aPreferredSize,
|
||||
&newRepresentation, 1.0f, aIsEntirelyBlack);
|
||||
aImage, aWhichFrame, aSVGContext, aPreferredSize, &newRepresentation,
|
||||
1.0f, aIsEntirelyBlack);
|
||||
if (NS_FAILED(rv) || !newRepresentation) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -609,9 +609,9 @@ nsresult nsCocoaUtils::CreateDualRepresentationNSImageFromImageContainer(
|
||||
[newRepresentation release];
|
||||
newRepresentation = nil;
|
||||
|
||||
rv = CreateNSImageFromImageContainer(
|
||||
aImage, aWhichFrame, aPresContext, aComputedStyle, aPreferredSize,
|
||||
&newRepresentation, 2.0f, aIsEntirelyBlack);
|
||||
rv = CreateNSImageFromImageContainer(aImage, aWhichFrame, aSVGContext,
|
||||
aPreferredSize, &newRepresentation, 2.0f,
|
||||
aIsEntirelyBlack);
|
||||
if (NS_FAILED(rv) || !newRepresentation) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -307,8 +307,8 @@ static constexpr nsCursor kCustomCursor = eCursorCount;
|
||||
const NSSize cocoaSize = NSMakeSize(size.width, size.height);
|
||||
NSImage* cursorImage;
|
||||
nsresult rv = nsCocoaUtils::CreateNSImageFromImageContainer(
|
||||
aCursor.mContainer, imgIContainer::FRAME_FIRST, nullptr, nullptr,
|
||||
cocoaSize, &cursorImage, scaleFactor);
|
||||
aCursor.mContainer, imgIContainer::FRAME_FIRST, nullptr, cocoaSize,
|
||||
&cursorImage, scaleFactor);
|
||||
if (NS_FAILED(rv) || !cursorImage) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -24,12 +24,15 @@ class nsMacDockSupport : public nsIMacDockSupport, public nsITaskbarProgress {
|
||||
|
||||
nsCOMPtr<nsIStandaloneNativeMenu> mDockMenu;
|
||||
nsString mBadgeText;
|
||||
bool mHasBadgeImage;
|
||||
|
||||
NSView* mDockTileWrapperView;
|
||||
NSImageView* mDockBadgeView;
|
||||
MOZProgressDockOverlayView* mProgressDockOverlayView;
|
||||
|
||||
nsTaskbarProgressState mProgressState;
|
||||
double mProgressFraction;
|
||||
|
||||
void BuildDockTile();
|
||||
nsresult UpdateDockTile();
|
||||
};
|
||||
|
@ -13,6 +13,10 @@
|
||||
#include "nsObjCExceptions.h"
|
||||
#include "nsNativeThemeColors.h"
|
||||
#include "nsString.h"
|
||||
#include "imgLoader.h"
|
||||
#include "MOZIconHelper.h"
|
||||
#include "mozilla/SVGImageContext.h"
|
||||
#include "nsISVGPaintContext.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsMacDockSupport, nsIMacDockSupport, nsITaskbarProgress)
|
||||
|
||||
@ -71,7 +75,9 @@ NS_IMPL_ISUPPORTS(nsMacDockSupport, nsIMacDockSupport, nsITaskbarProgress)
|
||||
@end
|
||||
|
||||
nsMacDockSupport::nsMacDockSupport()
|
||||
: mDockTileWrapperView(nil),
|
||||
: mHasBadgeImage(false),
|
||||
mDockTileWrapperView(nil),
|
||||
mDockBadgeView(nil),
|
||||
mProgressDockOverlayView(nil),
|
||||
mProgressState(STATE_NO_PROGRESS),
|
||||
mProgressFraction(0.0) {}
|
||||
@ -81,6 +87,10 @@ nsMacDockSupport::~nsMacDockSupport() {
|
||||
[mDockTileWrapperView release];
|
||||
mDockTileWrapperView = nil;
|
||||
}
|
||||
if (mDockBadgeView) {
|
||||
[mDockBadgeView release];
|
||||
mDockBadgeView = nil;
|
||||
}
|
||||
if (mProgressDockOverlayView) {
|
||||
[mProgressDockOverlayView release];
|
||||
mProgressDockOverlayView = nil;
|
||||
@ -117,14 +127,18 @@ nsMacDockSupport::SetBadgeText(const nsAString& aBadgeText) {
|
||||
|
||||
NSDockTile* tile = [[NSApplication sharedApplication] dockTile];
|
||||
mBadgeText = aBadgeText;
|
||||
if (aBadgeText.IsEmpty())
|
||||
if (aBadgeText.IsEmpty()) {
|
||||
[tile setBadgeLabel:nil];
|
||||
else
|
||||
} else {
|
||||
SetBadgeImage(nullptr, nullptr);
|
||||
|
||||
[tile
|
||||
setBadgeLabel:[NSString
|
||||
stringWithCharacters:reinterpret_cast<const unichar*>(
|
||||
mBadgeText.get())
|
||||
length:mBadgeText.Length()]];
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
|
||||
@ -136,6 +150,45 @@ nsMacDockSupport::GetBadgeText(nsAString& aBadgeText) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMacDockSupport::SetBadgeImage(imgIContainer* aImage,
|
||||
nsISVGPaintContext* aPaintContext) {
|
||||
if (!aImage) {
|
||||
mHasBadgeImage = false;
|
||||
if (mDockBadgeView) {
|
||||
mDockBadgeView.image = nullptr;
|
||||
}
|
||||
|
||||
return UpdateDockTile();
|
||||
}
|
||||
|
||||
if (!mBadgeText.IsEmpty()) {
|
||||
mBadgeText.Truncate();
|
||||
NSDockTile* tile = [[NSApplication sharedApplication] dockTile];
|
||||
[tile setBadgeLabel:nil];
|
||||
}
|
||||
|
||||
NS_OBJC_BEGIN_TRY_BLOCK_RETURN
|
||||
|
||||
mHasBadgeImage = true;
|
||||
BuildDockTile();
|
||||
|
||||
mozilla::SVGImageContext svgContext;
|
||||
mozilla::SVGImageContext::MaybeStoreContextPaint(svgContext, aPaintContext,
|
||||
aImage);
|
||||
NSImage* image =
|
||||
[MOZIconHelper iconImageFromImageContainer:aImage
|
||||
withSize:NSMakeSize(256, 256)
|
||||
svgContext:&svgContext
|
||||
scaleFactor:0.0];
|
||||
image.resizingMode = NSImageResizingModeStretch;
|
||||
mDockBadgeView.image = image;
|
||||
|
||||
return UpdateDockTile();
|
||||
|
||||
NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMacDockSupport::SetProgressState(nsTaskbarProgressState aState,
|
||||
uint64_t aCurrentValue, uint64_t aMaxValue) {
|
||||
@ -158,46 +211,67 @@ nsMacDockSupport::SetProgressState(nsTaskbarProgressState aState,
|
||||
return UpdateDockTile();
|
||||
}
|
||||
|
||||
void nsMacDockSupport::BuildDockTile() {
|
||||
if (!mDockTileWrapperView) {
|
||||
// Create the following NSView hierarchy:
|
||||
// * mDockTileWrapperView (NSView)
|
||||
// * imageView (NSImageView) <- has the application icon
|
||||
// * mDockBadgeView (NSImageView) <- has the dock badge
|
||||
// * mProgressDockOverlayView (MOZProgressDockOverlayView) <- draws the
|
||||
// progress bar
|
||||
|
||||
mDockTileWrapperView =
|
||||
[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 32, 32)];
|
||||
mDockTileWrapperView.autoresizingMask =
|
||||
NSViewWidthSizable | NSViewHeightSizable;
|
||||
|
||||
NSImageView* imageView =
|
||||
[[NSImageView alloc] initWithFrame:[mDockTileWrapperView bounds]];
|
||||
imageView.image = [NSImage imageNamed:@"NSApplicationIcon"];
|
||||
imageView.imageScaling = NSImageScaleAxesIndependently;
|
||||
imageView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
[mDockTileWrapperView addSubview:imageView];
|
||||
|
||||
mDockBadgeView =
|
||||
[[NSImageView alloc] initWithFrame:NSMakeRect(19.5, 19.5, 12, 12)];
|
||||
mDockBadgeView.imageScaling = NSImageScaleProportionallyUpOrDown;
|
||||
mDockBadgeView.autoresizingMask = NSViewMinXMargin | NSViewWidthSizable |
|
||||
NSViewMaxXMargin | NSViewMinYMargin |
|
||||
NSViewHeightSizable | NSViewMaxYMargin;
|
||||
[mDockTileWrapperView addSubview:mDockBadgeView];
|
||||
|
||||
mProgressDockOverlayView = [[MOZProgressDockOverlayView alloc]
|
||||
initWithFrame:NSMakeRect(1, 3, 30, 4)];
|
||||
mProgressDockOverlayView.autoresizingMask =
|
||||
NSViewMinXMargin | NSViewWidthSizable | NSViewMaxXMargin |
|
||||
NSViewMinYMargin | NSViewHeightSizable | NSViewMaxYMargin;
|
||||
[mDockTileWrapperView addSubview:mProgressDockOverlayView];
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsMacDockSupport::UpdateDockTile() {
|
||||
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
|
||||
|
||||
if (mProgressState == STATE_NORMAL || mProgressState == STATE_INDETERMINATE) {
|
||||
if (!mDockTileWrapperView) {
|
||||
// Create the following NSView hierarchy:
|
||||
// * mDockTileWrapperView (NSView)
|
||||
// * imageView (NSImageView) <- has the application icon
|
||||
// * mProgressDockOverlayView (MOZProgressDockOverlayView) <- draws the
|
||||
// progress bar
|
||||
if (mProgressState == STATE_NORMAL || mProgressState == STATE_INDETERMINATE ||
|
||||
mHasBadgeImage) {
|
||||
BuildDockTile();
|
||||
|
||||
mDockTileWrapperView =
|
||||
[[NSView alloc] initWithFrame:NSMakeRect(0, 0, 32, 32)];
|
||||
mDockTileWrapperView.autoresizingMask =
|
||||
NSViewWidthSizable | NSViewHeightSizable;
|
||||
|
||||
NSImageView* imageView =
|
||||
[[NSImageView alloc] initWithFrame:[mDockTileWrapperView bounds]];
|
||||
imageView.image = [NSImage imageNamed:@"NSApplicationIcon"];
|
||||
imageView.imageScaling = NSImageScaleAxesIndependently;
|
||||
imageView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
[mDockTileWrapperView addSubview:imageView];
|
||||
|
||||
mProgressDockOverlayView = [[MOZProgressDockOverlayView alloc]
|
||||
initWithFrame:NSMakeRect(1, 3, 30, 4)];
|
||||
mProgressDockOverlayView.autoresizingMask =
|
||||
NSViewMinXMargin | NSViewWidthSizable | NSViewMaxXMargin |
|
||||
NSViewMinYMargin | NSViewHeightSizable | NSViewMaxYMargin;
|
||||
[mDockTileWrapperView addSubview:mProgressDockOverlayView];
|
||||
}
|
||||
if (NSApp.dockTile.contentView != mDockTileWrapperView) {
|
||||
NSApp.dockTile.contentView = mDockTileWrapperView;
|
||||
}
|
||||
|
||||
mDockBadgeView.hidden = !mHasBadgeImage;
|
||||
|
||||
if (mProgressState == STATE_NORMAL) {
|
||||
mProgressDockOverlayView.fractionValue = mProgressFraction;
|
||||
} else {
|
||||
mProgressDockOverlayView.hidden = false;
|
||||
} else if (mProgressState == STATE_INDETERMINATE) {
|
||||
// Indeterminate states are rare. Just fill the entire progress bar in
|
||||
// that case.
|
||||
mProgressDockOverlayView.fractionValue = 1.0;
|
||||
mProgressDockOverlayView.hidden = false;
|
||||
} else {
|
||||
mProgressDockOverlayView.hidden = true;
|
||||
}
|
||||
[NSApp.dockTile display];
|
||||
} else if (NSApp.dockTile.contentView) {
|
||||
|
@ -24,6 +24,7 @@
|
||||
#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"
|
||||
@ -152,11 +153,17 @@ nsresult nsMenuItemIconX::OnComplete(imgIContainer* aImage) {
|
||||
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)
|
||||
presContext:pc
|
||||
computedStyle:mComputedStyle
|
||||
svgContext:svgContext.get()
|
||||
scaleFactor:0.0f] retain];
|
||||
mComputedStyle = nullptr;
|
||||
mPresContext = nullptr;
|
||||
|
@ -127,8 +127,7 @@ nsresult nsTouchBarInputIcon::OnComplete(imgIContainer* aImage) {
|
||||
NSImage* image = [MOZIconHelper
|
||||
iconImageFromImageContainer:aImage
|
||||
withSize:NSMakeSize(kIconHeight, kIconHeight)
|
||||
presContext:nullptr
|
||||
computedStyle:nullptr
|
||||
svgContext:nullptr
|
||||
scaleFactor:kHiDPIScalingFactor];
|
||||
[mButton setImage:image];
|
||||
[mShareScrubber setButtonImage:image];
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIStandaloneNativeMenu;
|
||||
interface nsISVGPaintContext;
|
||||
interface imgIContainer;
|
||||
|
||||
/**
|
||||
* Allow applications to interface with the Mac OS X Dock.
|
||||
@ -33,10 +35,17 @@ interface nsIMacDockSupport : nsISupports
|
||||
void activateApplication(in boolean aIgnoreOtherApplications);
|
||||
|
||||
/**
|
||||
* Text used to badge the dock tile.
|
||||
* Text used to badge the dock tile. Setting this will remove any badge image.
|
||||
*/
|
||||
attribute AString badgeText;
|
||||
|
||||
/**
|
||||
* An image to add to the dock icon as a badge. Setting this will remove any
|
||||
* badgeText. If an SVG image is passed the given paint context is used to
|
||||
* set the stroke and fill properties.
|
||||
*/
|
||||
void setBadgeImage(in imgIContainer aBadgeImage, [optional] in nsISVGPaintContext aPaintContext);
|
||||
|
||||
/**
|
||||
* True if this app is in the list of apps that are persisted to the macOS
|
||||
* Dock (as if the user selected "Keep in Dock").
|
||||
|
Loading…
Reference in New Issue
Block a user