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/. */
7 * Retrieves and displays icons on the macOS Touch Bar.
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"
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),
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];
45 NS_ERROR("Incompatible Touch Bar input passed to nsTouchBarInputIcon.");
48 MOZ_COUNT_CTOR(nsTouchBarInputIcon);
51 nsTouchBarInputIcon::~nsTouchBarInputIcon() {
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() {
62 mIconLoader->Destroy();
63 mIconLoader = nullptr;
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
80 if (!(mButton || mShareScrubber || mPopoverItem)) {
81 NS_ERROR("No Touch Bar input provided.");
82 return NS_ERROR_FAILURE;
86 mIconLoader = new IconLoader(this);
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];
99 mIconLoader->LoadIcon(aIconURI, mDocument, true /* aIsInternalIcon */);
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];
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)
131 computedStyle:nullptr
132 scaleFactor:kHiDPIScalingFactor];
133 [mButton setImage:image];
134 [mShareScrubber setButtonImage:image];
135 [mPopoverItem setCollapsedRepresentationImage:image];
137 mIconLoader->Destroy();
140 NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE)