widget/cocoa/nsMacDockSupport.mm

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #import <Cocoa/Cocoa.h>
michael@0 7
michael@0 8 #include "nsComponentManagerUtils.h"
michael@0 9 #include "nsMacDockSupport.h"
michael@0 10 #include "nsObjCExceptions.h"
michael@0 11
michael@0 12 NS_IMPL_ISUPPORTS(nsMacDockSupport, nsIMacDockSupport, nsITaskbarProgress)
michael@0 13
michael@0 14 nsMacDockSupport::nsMacDockSupport()
michael@0 15 : mAppIcon(nil)
michael@0 16 , mProgressBackground(nil)
michael@0 17 , mProgressState(STATE_NO_PROGRESS)
michael@0 18 , mProgressFraction(0.0)
michael@0 19 {
michael@0 20 mProgressTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
michael@0 21 }
michael@0 22
michael@0 23 nsMacDockSupport::~nsMacDockSupport()
michael@0 24 {
michael@0 25 if (mAppIcon) {
michael@0 26 [mAppIcon release];
michael@0 27 mAppIcon = nil;
michael@0 28 }
michael@0 29 if (mProgressBackground) {
michael@0 30 [mProgressBackground release];
michael@0 31 mProgressBackground = nil;
michael@0 32 }
michael@0 33 if (mProgressTimer) {
michael@0 34 mProgressTimer->Cancel();
michael@0 35 mProgressTimer = nullptr;
michael@0 36 }
michael@0 37 }
michael@0 38
michael@0 39 NS_IMETHODIMP
michael@0 40 nsMacDockSupport::GetDockMenu(nsIStandaloneNativeMenu ** aDockMenu)
michael@0 41 {
michael@0 42 *aDockMenu = nullptr;
michael@0 43
michael@0 44 if (mDockMenu)
michael@0 45 return mDockMenu->QueryInterface(NS_GET_IID(nsIStandaloneNativeMenu),
michael@0 46 reinterpret_cast<void **>(aDockMenu));
michael@0 47 return NS_OK;
michael@0 48 }
michael@0 49
michael@0 50 NS_IMETHODIMP
michael@0 51 nsMacDockSupport::SetDockMenu(nsIStandaloneNativeMenu * aDockMenu)
michael@0 52 {
michael@0 53 nsresult rv;
michael@0 54 mDockMenu = do_QueryInterface(aDockMenu, &rv);
michael@0 55 return rv;
michael@0 56 }
michael@0 57
michael@0 58 NS_IMETHODIMP
michael@0 59 nsMacDockSupport::ActivateApplication(bool aIgnoreOtherApplications)
michael@0 60 {
michael@0 61 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
michael@0 62
michael@0 63 [[NSApplication sharedApplication] activateIgnoringOtherApps:aIgnoreOtherApplications];
michael@0 64 return NS_OK;
michael@0 65
michael@0 66 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
michael@0 67 }
michael@0 68
michael@0 69 NS_IMETHODIMP
michael@0 70 nsMacDockSupport::SetBadgeText(const nsAString& aBadgeText)
michael@0 71 {
michael@0 72 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
michael@0 73
michael@0 74 NSDockTile *tile = [[NSApplication sharedApplication] dockTile];
michael@0 75 mBadgeText = aBadgeText;
michael@0 76 if (aBadgeText.IsEmpty())
michael@0 77 [tile setBadgeLabel: nil];
michael@0 78 else
michael@0 79 [tile setBadgeLabel:[NSString stringWithCharacters:reinterpret_cast<const unichar*>(mBadgeText.get())
michael@0 80 length:mBadgeText.Length()]];
michael@0 81 return NS_OK;
michael@0 82
michael@0 83 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
michael@0 84 }
michael@0 85
michael@0 86 NS_IMETHODIMP
michael@0 87 nsMacDockSupport::GetBadgeText(nsAString& aBadgeText)
michael@0 88 {
michael@0 89 aBadgeText = mBadgeText;
michael@0 90 return NS_OK;
michael@0 91 }
michael@0 92
michael@0 93 NS_IMETHODIMP
michael@0 94 nsMacDockSupport::SetProgressState(nsTaskbarProgressState aState,
michael@0 95 uint64_t aCurrentValue,
michael@0 96 uint64_t aMaxValue)
michael@0 97 {
michael@0 98 NS_ENSURE_ARG_RANGE(aState, 0, STATE_PAUSED);
michael@0 99 if (aState == STATE_NO_PROGRESS || aState == STATE_INDETERMINATE) {
michael@0 100 NS_ENSURE_TRUE(aCurrentValue == 0, NS_ERROR_INVALID_ARG);
michael@0 101 NS_ENSURE_TRUE(aMaxValue == 0, NS_ERROR_INVALID_ARG);
michael@0 102 }
michael@0 103 if (aCurrentValue > aMaxValue) {
michael@0 104 return NS_ERROR_ILLEGAL_VALUE;
michael@0 105 }
michael@0 106
michael@0 107 mProgressState = aState;
michael@0 108 if (aMaxValue == 0) {
michael@0 109 mProgressFraction = 0;
michael@0 110 } else {
michael@0 111 mProgressFraction = (double)aCurrentValue / aMaxValue;
michael@0 112 }
michael@0 113
michael@0 114 if (mProgressState == STATE_NORMAL || mProgressState == STATE_INDETERMINATE) {
michael@0 115 int perSecond = 8; // Empirically determined, see bug 848792
michael@0 116 mProgressTimer->InitWithFuncCallback(RedrawIconCallback, this, 1000 / perSecond,
michael@0 117 nsITimer::TYPE_REPEATING_SLACK);
michael@0 118 return NS_OK;
michael@0 119 } else {
michael@0 120 mProgressTimer->Cancel();
michael@0 121 return RedrawIcon();
michael@0 122 }
michael@0 123 }
michael@0 124
michael@0 125 // static
michael@0 126 void nsMacDockSupport::RedrawIconCallback(nsITimer* aTimer, void* aClosure)
michael@0 127 {
michael@0 128 static_cast<nsMacDockSupport*>(aClosure)->RedrawIcon();
michael@0 129 }
michael@0 130
michael@0 131 // Return whether to draw progress
michael@0 132 bool nsMacDockSupport::InitProgress()
michael@0 133 {
michael@0 134 if (mProgressState != STATE_NORMAL && mProgressState != STATE_INDETERMINATE) {
michael@0 135 return false;
michael@0 136 }
michael@0 137
michael@0 138 if (!mAppIcon) {
michael@0 139 mProgressTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
michael@0 140 mAppIcon = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
michael@0 141 mProgressBackground = [mAppIcon copyWithZone:nil];
michael@0 142 mTheme = new nsNativeThemeCocoa();
michael@0 143
michael@0 144 NSSize sz = [mProgressBackground size];
michael@0 145 mProgressBounds = CGRectMake(sz.width * 1/32, sz.height * 3/32,
michael@0 146 sz.width * 30/32, sz.height * 4/32);
michael@0 147 [mProgressBackground lockFocus];
michael@0 148 [[NSColor whiteColor] set];
michael@0 149 NSRectFill(NSRectFromCGRect(mProgressBounds));
michael@0 150 [mProgressBackground unlockFocus];
michael@0 151 }
michael@0 152 return true;
michael@0 153 }
michael@0 154
michael@0 155 nsresult
michael@0 156 nsMacDockSupport::RedrawIcon()
michael@0 157 {
michael@0 158 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
michael@0 159
michael@0 160 if (InitProgress()) {
michael@0 161 // TODO: - Implement ERROR and PAUSED states?
michael@0 162 NSImage *icon = [mProgressBackground copyWithZone:nil];
michael@0 163 bool isIndeterminate = (mProgressState != STATE_NORMAL);
michael@0 164
michael@0 165 [icon lockFocus];
michael@0 166 CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
michael@0 167 mTheme->DrawProgress(ctx, mProgressBounds, isIndeterminate,
michael@0 168 true, mProgressFraction, 1.0, NULL);
michael@0 169 [icon unlockFocus];
michael@0 170 [NSApp setApplicationIconImage:icon];
michael@0 171 [icon release];
michael@0 172 } else {
michael@0 173 [NSApp setApplicationIconImage:mAppIcon];
michael@0 174 }
michael@0 175
michael@0 176 return NS_OK;
michael@0 177 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
michael@0 178 }

mercurial