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, 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];
39 NS_ERROR("Incompatible Touch Bar input passed to nsTouchBarInputIcon.");
42 MOZ_COUNT_CTOR(nsTouchBarInputIcon);
45 nsTouchBarInputIcon::~nsTouchBarInputIcon() {
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() {
56 mIconLoader->Destroy();
57 mIconLoader = nullptr;
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
74 if (!(mButton || mShareScrubber || mPopoverItem)) {
75 NS_ERROR("No Touch Bar input provided.");
76 return NS_ERROR_FAILURE;
80 mIconLoader = new IconLoader(this);
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];
92 nsresult rv = mIconLoader->LoadIcon(aIconURI, mDocument, true /* aIsInternalIcon */);
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];
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)
123 computedStyle:nullptr
124 scaleFactor:kHiDPIScalingFactor];
125 [mButton setImage:image];
126 [mShareScrubber setButtonImage:image];
127 [mPopoverItem setCollapsedRepresentationImage:image];
129 mIconLoader->Destroy();
132 NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE)