Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / widget / cocoa / nsTouchBarInputIcon.mm
blob69e0c2aa0fc9518ac6fd879a205e9a6be791530e
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,
29                                          TouchBarInput* aInput,
30                                          NSTouchBarItem* aItem)
31     : mDocument(aDocument),
32       mSetIcon(false),
33       mButton(nil),
34       mShareScrubber(nil),
35       mPopoverItem(nil) {
36   if ([[aInput nativeIdentifier]
37           isEqualToString:[TouchBarInput shareScrubberIdentifier]]) {
38     mShareScrubber = (NSSharingServicePickerTouchBarItem*)aItem;
39   } else if ([aInput baseType] == TouchBarInputBaseType::kPopover) {
40     mPopoverItem = (NSPopoverTouchBarItem*)aItem;
41   } else if ([aInput baseType] == TouchBarInputBaseType::kButton ||
42              [aInput baseType] == TouchBarInputBaseType::kMainButton) {
43     mButton = (NSButton*)[aItem view];
44   } else {
45     NS_ERROR("Incompatible Touch Bar input passed to nsTouchBarInputIcon.");
46   }
47   aInput = nil;
48   MOZ_COUNT_CTOR(nsTouchBarInputIcon);
51 nsTouchBarInputIcon::~nsTouchBarInputIcon() {
52   Destroy();
53   MOZ_COUNT_DTOR(nsTouchBarInputIcon);
56 // Called from nsTouchBar's destructor, to prevent us from outliving it
57 // (as might otherwise happen if calls to our imgINotificationObserver methods
58 // are still outstanding).  nsTouchBar owns our mTouchBarInput.
59 void nsTouchBarInputIcon::Destroy() {
60   ReleaseJSObjects();
61   if (mIconLoader) {
62     mIconLoader->Destroy();
63     mIconLoader = nullptr;
64   }
66   mButton = nil;
67   mShareScrubber = nil;
68   mPopoverItem = nil;
71 nsresult nsTouchBarInputIcon::SetupIcon(nsCOMPtr<nsIURI> aIconURI) {
72   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
74   // We might not have a document if the Touch Bar tries to update when the main
75   // window is closed.
76   if (!mDocument) {
77     return NS_OK;
78   }
80   if (!(mButton || mShareScrubber || mPopoverItem)) {
81     NS_ERROR("No Touch Bar input provided.");
82     return NS_ERROR_FAILURE;
83   }
85   if (!mIconLoader) {
86     mIconLoader = new IconLoader(this);
87   }
89   if (!mSetIcon) {
90     // Load placeholder icon.
91     NSSize iconSize = NSMakeSize(kIconHeight, kIconHeight);
92     NSImage* placeholder = [MOZIconHelper placeholderIconWithSize:iconSize];
93     [mButton setImage:placeholder];
94     [mShareScrubber setButtonImage:placeholder];
95     [mPopoverItem setCollapsedRepresentationImage:placeholder];
96   }
98   nsresult rv =
99       mIconLoader->LoadIcon(aIconURI, mDocument, true /* aIsInternalIcon */);
100   if (NS_FAILED(rv)) {
101     // There is no icon for this menu item, as an error occurred while loading
102     // it. An icon might have been set earlier or the place holder icon may have
103     // been set.  Clear it.
104     [mButton setImage:nil];
105     [mShareScrubber setButtonImage:nil];
106     [mPopoverItem setCollapsedRepresentationImage:nil];
107   }
109   mSetIcon = true;
111   return rv;
113   NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
116 void nsTouchBarInputIcon::ReleaseJSObjects() { mDocument = nil; }
119 // mozilla::widget::IconLoader::Listener
122 nsresult nsTouchBarInputIcon::OnComplete(imgIContainer* aImage) {
123   NS_OBJC_BEGIN_TRY_BLOCK_RETURN
125   // We ask only for the HiDPI images since all Touch Bars are Retina
126   // displays and we have no need for icons @1x.
127   NSImage* image = [MOZIconHelper
128       iconImageFromImageContainer:aImage
129                          withSize:NSMakeSize(kIconHeight, kIconHeight)
130                       presContext:nullptr
131                     computedStyle:nullptr
132                       scaleFactor:kHiDPIScalingFactor];
133   [mButton setImage:image];
134   [mShareScrubber setButtonImage:image];
135   [mPopoverItem setCollapsedRepresentationImage:image];
137   mIconLoader->Destroy();
138   return NS_OK;
140   NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE)