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