author | Markus Stange <mstange@themasta.com> |
Fri, 28 Jun 2019 14:17:47 +0000 | |
changeset 480564 | 9823d19217e209619c3f8d0e52d88119ba238fef |
parent 480563 | 0c6e149ba01d55dfa0e21e0eed6cfa2ec9aad90f |
child 480565 | 1b5308f24205634af9d3aeafa3a84854394ca758 |
push id | 88769 |
push user | mstange@themasta.com |
push date | Fri, 28 Jun 2019 14:28:21 +0000 |
treeherder | autoland@9823d19217e2 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | spohl |
bugs | 1562032 |
milestone | 69.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
widget/cocoa/nsMacDockSupport.h | file | annotate | diff | comparison | revisions | |
widget/cocoa/nsMacDockSupport.mm | file | annotate | diff | comparison | revisions |
--- a/widget/cocoa/nsMacDockSupport.h +++ b/widget/cocoa/nsMacDockSupport.h @@ -4,37 +4,33 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsIMacDockSupport.h" #include "nsIStandaloneNativeMenu.h" #include "nsITaskbarProgress.h" #include "nsITimer.h" #include "nsCOMPtr.h" #include "nsString.h" -#include "nsNativeThemeCocoa.h" + +@class MOZProgressDockOverlayView; class nsMacDockSupport : public nsIMacDockSupport, public nsITaskbarProgress { public: nsMacDockSupport(); NS_DECL_ISUPPORTS NS_DECL_NSIMACDOCKSUPPORT NS_DECL_NSITASKBARPROGRESS protected: virtual ~nsMacDockSupport(); nsCOMPtr<nsIStandaloneNativeMenu> mDockMenu; nsString mBadgeText; - NSImage *mAppIcon, *mProgressBackground; + NSView* mDockTileWrapperView; + MOZProgressDockOverlayView* mProgressDockOverlayView; - HIRect mProgressBounds; nsTaskbarProgressState mProgressState; double mProgressFraction; - nsCOMPtr<nsITimer> mProgressTimer; - RefPtr<nsNativeThemeCocoa> mTheme; - static void RedrawIconCallback(nsITimer* aTimer, void* aClosure); - - bool InitProgress(); - nsresult RedrawIcon(); + nsresult UpdateDockTile(); };
--- a/widget/cocoa/nsMacDockSupport.mm +++ b/widget/cocoa/nsMacDockSupport.mm @@ -6,37 +6,83 @@ #import <Cocoa/Cocoa.h> #include "nsComponentManagerUtils.h" #include "nsMacDockSupport.h" #include "nsObjCExceptions.h" NS_IMPL_ISUPPORTS(nsMacDockSupport, nsIMacDockSupport, nsITaskbarProgress) +// This view is used in the dock tile when we're downloading a file. +// It draws a progress bar that looks similar to the native progress bar on +// 10.12. This style of progress bar is not animated, unlike the pre-10.10 +// progress bar look which had to redrawn multiple times per second. +@interface MOZProgressDockOverlayView : NSView { + double mFractionValue; +} +@property double fractionValue; + +@end + +@implementation MOZProgressDockOverlayView + +@synthesize fractionValue = mFractionValue; + +- (void)drawRect:(NSRect)aRect { + // Erase the background behind this view, i.e. cut a rectangle hole in the icon. + [[NSColor clearColor] set]; + NSRectFill(self.bounds); + + // Split the height of this view into four quarters. The middle two quarters + // will be covered by the actual progress bar. + CGFloat radius = self.bounds.size.height / 4; + NSRect barBounds = NSInsetRect(self.bounds, 0, radius); + + NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:barBounds + xRadius:radius + yRadius:radius]; + + // Draw a grayish background first. + [[NSColor colorWithDeviceWhite:0 alpha:0.1] setFill]; + [path fill]; + + // Draw a blue or gray fill (depending on graphite or not) for the progress part. + NSRect progressFillRect = self.bounds; + progressFillRect.size.width *= mFractionValue; + [NSGraphicsContext saveGraphicsState]; + [NSBezierPath clipRect:progressFillRect]; + [[NSColor keyboardFocusIndicatorColor] setFill]; + [path fill]; + [NSGraphicsContext restoreGraphicsState]; + + // Add a shadowy stroke on top. + [NSGraphicsContext saveGraphicsState]; + [path addClip]; + [[NSColor colorWithDeviceWhite:0 alpha:0.2] setStroke]; + path.lineWidth = barBounds.size.height / 10; + [path stroke]; + [NSGraphicsContext restoreGraphicsState]; +} + +@end + nsMacDockSupport::nsMacDockSupport() - : mAppIcon(nil), - mProgressBackground(nil), - mProgressBounds(), + : mDockTileWrapperView(nil), + mProgressDockOverlayView(nil), mProgressState(STATE_NO_PROGRESS), - mProgressFraction(0.0) { - mProgressTimer = NS_NewTimer(); -} + mProgressFraction(0.0) {} nsMacDockSupport::~nsMacDockSupport() { - if (mAppIcon) { - [mAppIcon release]; - mAppIcon = nil; + if (mDockTileWrapperView) { + [mDockTileWrapperView release]; + mDockTileWrapperView = nil; } - if (mProgressBackground) { - [mProgressBackground release]; - mProgressBackground = nil; - } - if (mProgressTimer) { - mProgressTimer->Cancel(); - mProgressTimer = nullptr; + if (mProgressDockOverlayView) { + [mProgressDockOverlayView release]; + mProgressDockOverlayView = nil; } } NS_IMETHODIMP nsMacDockSupport::GetDockMenu(nsIStandaloneNativeMenu** aDockMenu) { nsCOMPtr<nsIStandaloneNativeMenu> dockMenu(mDockMenu); dockMenu.forget(aDockMenu); return NS_OK; @@ -95,74 +141,57 @@ nsMacDockSupport::SetProgressState(nsTas mProgressState = aState; if (aMaxValue == 0) { mProgressFraction = 0; } else { mProgressFraction = (double)aCurrentValue / aMaxValue; } - if (mProgressState == STATE_NORMAL || mProgressState == STATE_INDETERMINATE) { - int perSecond = 8; // Empirically determined, see bug 848792 - mProgressTimer->InitWithNamedFuncCallback(RedrawIconCallback, this, 1000 / perSecond, - nsITimer::TYPE_REPEATING_SLACK, - "nsMacDockSupport::RedrawIconCallback"); - return NS_OK; - } else { - mProgressTimer->Cancel(); - return RedrawIcon(); - } -} - -// static -void nsMacDockSupport::RedrawIconCallback(nsITimer* aTimer, void* aClosure) { - static_cast<nsMacDockSupport*>(aClosure)->RedrawIcon(); + return UpdateDockTile(); } -// Return whether to draw progress -bool nsMacDockSupport::InitProgress() { - if (mProgressState != STATE_NORMAL && mProgressState != STATE_INDETERMINATE) { - return false; - } - - if (!mAppIcon) { - mProgressTimer = NS_NewTimer(); - mAppIcon = [[NSImage imageNamed:@"NSApplicationIcon"] retain]; - mProgressBackground = [mAppIcon copyWithZone:nil]; - mTheme = new nsNativeThemeCocoa(); - - NSSize sz = [mProgressBackground size]; - mProgressBounds = - CGRectMake(sz.width * 1 / 32, sz.height * 3 / 32, sz.width * 30 / 32, sz.height * 4 / 32); - [mProgressBackground lockFocus]; - [[NSColor clearColor] set]; - NSRectFill(NSRectFromCGRect(mProgressBounds)); - [mProgressBackground unlockFocus]; - } - return true; -} - -nsresult nsMacDockSupport::RedrawIcon() { +nsresult nsMacDockSupport::UpdateDockTile() { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - if (InitProgress()) { - // TODO: - Implement ERROR and PAUSED states? - NSImage* icon = [mProgressBackground copyWithZone:nil]; + 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 + + 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]; - [icon lockFocus]; - CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - nsNativeThemeCocoa::ProgressParams params; - params.value = mProgressFraction; - params.max = 1.0; - params.insideActiveWindow = true; - params.indeterminate = (mProgressState != STATE_NORMAL); - params.horizontal = true; - mTheme->DrawProgress(ctx, mProgressBounds, params); - [icon unlockFocus]; - [NSApp setApplicationIconImage:icon]; - [icon release]; - } else { - [NSApp setApplicationIconImage:mAppIcon]; + 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; + } + + if (mProgressState == STATE_NORMAL) { + mProgressDockOverlayView.fractionValue = mProgressFraction; + } else { + // Indeterminate states are rare. Just fill the entire progress bar in + // that case. + mProgressDockOverlayView.fractionValue = 1.0; + } + [NSApp.dockTile display]; + } else if (NSApp.dockTile.contentView) { + NSApp.dockTile.contentView = nil; + [NSApp.dockTile display]; } return NS_OK; NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; }