widget/cocoa/nsMacDockSupport.mm

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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)
    19 {
    20   mProgressTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
    21 }
    23 nsMacDockSupport::~nsMacDockSupport()
    24 {
    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   }
    37 }
    39 NS_IMETHODIMP
    40 nsMacDockSupport::GetDockMenu(nsIStandaloneNativeMenu ** aDockMenu)
    41 {
    42   *aDockMenu = nullptr;
    44   if (mDockMenu)
    45     return mDockMenu->QueryInterface(NS_GET_IID(nsIStandaloneNativeMenu),
    46                                      reinterpret_cast<void **>(aDockMenu));
    47   return NS_OK;
    48 }
    50 NS_IMETHODIMP
    51 nsMacDockSupport::SetDockMenu(nsIStandaloneNativeMenu * aDockMenu)
    52 {
    53   nsresult rv;
    54   mDockMenu = do_QueryInterface(aDockMenu, &rv);
    55   return rv;
    56 }
    58 NS_IMETHODIMP
    59 nsMacDockSupport::ActivateApplication(bool aIgnoreOtherApplications)
    60 {
    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;
    67 }
    69 NS_IMETHODIMP
    70 nsMacDockSupport::SetBadgeText(const nsAString& aBadgeText)
    71 {
    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;
    84 }
    86 NS_IMETHODIMP
    87 nsMacDockSupport::GetBadgeText(nsAString& aBadgeText)
    88 {
    89   aBadgeText = mBadgeText;
    90   return NS_OK;
    91 }
    93 NS_IMETHODIMP
    94 nsMacDockSupport::SetProgressState(nsTaskbarProgressState aState,
    95                                    uint64_t aCurrentValue,
    96                                    uint64_t aMaxValue)
    97 {
    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   }
   123 }
   125 // static
   126 void nsMacDockSupport::RedrawIconCallback(nsITimer* aTimer, void* aClosure)
   127 {
   128   static_cast<nsMacDockSupport*>(aClosure)->RedrawIcon();
   129 }
   131 // Return whether to draw progress
   132 bool nsMacDockSupport::InitProgress()
   133 {
   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;
   153 }
   155 nsresult
   156 nsMacDockSupport::RedrawIcon()
   157 {
   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;
   178 }

mercurial