Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / widget / cocoa / nsTouchBarInputIcon.mm
blobac9e907c8e1d16a80e5766016f002bc74f3d5af9
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 /*
7  * Retrieves and displays icons on the macOS Touch Bar.
8  */
10 #include "nsTouchBarInputIcon.h"
12 #include "MOZIconHelper.h"
13 #include "mozilla/dom/Document.h"
14 #include "nsCocoaUtils.h"
15 #include "nsComputedDOMStyle.h"
16 #include "nsContentUtils.h"
17 #include "nsGkAtoms.h"
18 #include "nsINode.h"
19 #include "nsNameSpaceManager.h"
20 #include "nsObjCExceptions.h"
22 using namespace mozilla;
23 using mozilla::widget::IconLoader;
25 static const uint32_t kIconHeight = 16;
26 static const CGFloat kHiDPIScalingFactor = 2.0f;
28 nsTouchBarInputIcon::nsTouchBarInputIcon(RefPtr<Document> aDocument, TouchBarInput* aInput,
29                                          NSTouchBarItem* aItem)
30     : mDocument(aDocument), mSetIcon(false), mButton(nil), mShareScrubber(nil), mPopoverItem(nil) {
31   if ([[aInput nativeIdentifier] isEqualToString:[TouchBarInput shareScrubberIdentifier]]) {
32     mShareScrubber = (NSSharingServicePickerTouchBarItem*)aItem;
33   } else if ([aInput baseType] == TouchBarInputBaseType::kPopover) {
34     mPopoverItem = (NSPopoverTouchBarItem*)aItem;
35   } else if ([aInput baseType] == TouchBarInputBaseType::kButton ||
36              [aInput baseType] == TouchBarInputBaseType::kMainButton) {
37     mButton = (NSButton*)[aItem view];
38   } else {
39     NS_ERROR("Incompatible Touch Bar input passed to nsTouchBarInputIcon.");
40   }
41   aInput = nil;
42   MOZ_COUNT_CTOR(nsTouchBarInputIcon);
45 nsTouchBarInputIcon::~nsTouchBarInputIcon() {
46   Destroy();
47   MOZ_COUNT_DTOR(nsTouchBarInputIcon);
50 // Called from nsTouchBar's destructor, to prevent us from outliving it
51 // (as might otherwise happen if calls to our imgINotificationObserver methods
52 // are still outstanding).  nsTouchBar owns our mTouchBarInput.
53 void nsTouchBarInputIcon::Destroy() {
54   ReleaseJSObjects();
55   if (mIconLoader) {
56     mIconLoader->Destroy();
57     mIconLoader = nullptr;
58   }
60   mButton = nil;
61   mShareScrubber = nil;
62   mPopoverItem = nil;
65 nsresult nsTouchBarInputIcon::SetupIcon(nsCOMPtr<nsIURI> aIconURI) {
66   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
68   // We might not have a document if the Touch Bar tries to update when the main
69   // window is closed.
70   if (!mDocument) {
71     return NS_OK;
72   }
74   if (!(mButton || mShareScrubber || mPopoverItem)) {
75     NS_ERROR("No Touch Bar input provided.");
76     return NS_ERROR_FAILURE;
77   }
79   if (!mIconLoader) {
80     mIconLoader = new IconLoader(this);
81   }
83   if (!mSetIcon) {
84     // Load placeholder icon.
85     NSSize iconSize = NSMakeSize(kIconHeight, kIconHeight);
86     NSImage* placeholder = [MOZIconHelper placeholderIconWithSize:iconSize];
87     [mButton setImage:placeholder];
88     [mShareScrubber setButtonImage:placeholder];
89     [mPopoverItem setCollapsedRepresentationImage:placeholder];
90   }
92   nsresult rv = mIconLoader->LoadIcon(aIconURI, mDocument, true /* aIsInternalIcon */);
93   if (NS_FAILED(rv)) {
94     // There is no icon for this menu item, as an error occurred while loading it.
95     // An icon might have been set earlier or the place holder icon may have
96     // been set.  Clear it.
97     [mButton setImage:nil];
98     [mShareScrubber setButtonImage:nil];
99     [mPopoverItem setCollapsedRepresentationImage:nil];
100   }
102   mSetIcon = true;
104   return rv;
106   NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
109 void nsTouchBarInputIcon::ReleaseJSObjects() { mDocument = nil; }
112 // mozilla::widget::IconLoader::Listener
115 nsresult nsTouchBarInputIcon::OnComplete(imgIContainer* aImage) {
116   NS_OBJC_BEGIN_TRY_BLOCK_RETURN
118   // We ask only for the HiDPI images since all Touch Bars are Retina
119   // displays and we have no need for icons @1x.
120   NSImage* image = [MOZIconHelper iconImageFromImageContainer:aImage
121                                                      withSize:NSMakeSize(kIconHeight, kIconHeight)
122                                                   presContext:nullptr
123                                                 computedStyle:nullptr
124                                                   scaleFactor:kHiDPIScalingFactor];
125   [mButton setImage:image];
126   [mShareScrubber setButtonImage:image];
127   [mPopoverItem setCollapsedRepresentationImage:image];
129   mIconLoader->Destroy();
130   return NS_OK;
132   NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE)