about summary refs log tree commit diff
path: root/pkgs/build-support
diff options
context:
space:
mode:
authorBen Siraphob <bensiraphob@gmail.com>2022-03-24 22:12:56 -0500
committerGitHub <noreply@github.com>2022-03-24 22:12:56 -0500
commit3f1e23cf6825ebef5bdf66f1a104dd308a3ee500 (patch)
treeb0b83a4f7e93e0689da188365e8d3581695398fb /pkgs/build-support
parentc7c341796d0308562ea518869c9db5a9e032bda8 (diff)
parent6aa5c537483e9cc9cbd66ac28fef8800ba306f97 (diff)
Merge pull request #165113 from toonn/darwin-bundle-fix-icon
Diffstat (limited to 'pkgs/build-support')
-rw-r--r--pkgs/build-support/make-darwin-bundle/write-darwin-bundle.nix8
-rw-r--r--pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh48
2 files changed, 40 insertions, 16 deletions
diff --git a/pkgs/build-support/make-darwin-bundle/write-darwin-bundle.nix b/pkgs/build-support/make-darwin-bundle/write-darwin-bundle.nix
index d21e0475e2df5..fde977c3636b7 100644
--- a/pkgs/build-support/make-darwin-bundle/write-darwin-bundle.nix
+++ b/pkgs/build-support/make-darwin-bundle/write-darwin-bundle.nix
@@ -5,6 +5,7 @@ let
     CFBundleDevelopmentRegion = "English";
     CFBundleExecutable = "$name";
     CFBundleIconFile = "$icon";
+    CFBundleIconFiles = [ "$icon" ];
     CFBundleIdentifier = "org.nixos.$name";
     CFBundleInfoDictionaryVersion = "6.0";
     CFBundleName = "$name";
@@ -25,11 +26,8 @@ in writeScriptBin "write-darwin-bundle" ''
 ${pListText}
 EOF
 
-  if [[ $squircle != 0 && $squircle != "false" ]]; then
-    sed  "
-      s|CFBundleIconFile|CFBundleIconFiles|;
-      s|<string>$icon</string>|<array><string>$icon</string></array>|
-    " -i "$plist"
+  if [[ $squircle == 0 || $squircle == "false" ]]; then
+    sed  '/CFBundleIconFiles/,\|</array>|d' -i "$plist"
   fi
 
     cat > "$prefix/Applications/$name.app/Contents/MacOS/$name" <<EOF
diff --git a/pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh b/pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh
index b2e2738cb6ece..d54af90b68888 100644
--- a/pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh
+++ b/pkgs/build-support/setup-hooks/desktop-to-darwin-bundle.sh
@@ -18,7 +18,9 @@ convertIconTheme() {
     local -r iconName=$3
     local -r theme=${4:-hicolor}
 
-    local -ra iconSizes=(16 32 48 128 256 512)
+    # Sizes based on archived Apple documentation:
+    # https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/app-icon#app-icon-sizes
+    local -ra iconSizes=(16 32 128 256 512)
     local -ra scales=([1]="" [2]="@2")
 
     # Based loosely on the algorithm at:
@@ -31,13 +33,6 @@ convertIconTheme() {
         local scaleSuffix=${scales[$scale]}
         local exactSize=${iconSize}x${iconSize}${scaleSuffix}
 
-        if [[ $exactSize = '48x48@2' ]]; then
-            # macOS does not support a 2x scale variant of 48x48 icons
-            # See: https://en.wikipedia.org/wiki/Apple_Icon_Image_format#Icon_types
-            echo "unsupported"
-            return 0
-        fi
-
         local -a validSizes=(
             ${exactSize}
             $((iconSize + 1))x$((iconSize + 1))${scaleSuffix}
@@ -55,8 +50,10 @@ convertIconTheme() {
                     else
                         echo "threshold $icon"
                     fi
-                    return 0
+                elif [[ -a $icon ]]; then
+                  echo "fallback $icon"
                 fi
+                return 0
             done
         done
         echo "scalable"
@@ -106,6 +103,17 @@ convertIconTheme() {
             scalableIcon=('-')
         fi
 
+        # Tri-state variable, NONE means no icons have been found, an empty
+        # icns file will be generated, not sure that's necessary because macOS
+        # will default to a generic icon if no icon can be found.
+        #
+        # OTHER means an appropriate icon was found.
+        #
+        # Any other value is a path to an icon file that isn't scalable or
+        # within the threshold. This is used as a fallback in case no better
+        # icon can be found and will be scaled as much as
+        # necessary to result in appropriate icon sizes.
+        local foundIcon=NONE
         for iconSize in "${iconSizes[@]}"; do
             for scale in "${!scales[@]}"; do
                 local iconResult=$(findIcon $iconSize $scale)
@@ -117,6 +125,7 @@ convertIconTheme() {
                     fixed)
                         local density=$((72 * scale))x$((72 * scale))
                         magick convert -density "$density" -units PixelsPerInch "$icon" "$result"
+                        foundIcon=OTHER
                         ;;
                     threshold)
                         # Synthesize an icon of the exact size if a scalable icon is available
@@ -124,21 +133,38 @@ convertIconTheme() {
                         if ! synthesizeIcon "${scalableIcon[0]}" "$result" "$iconSize" "$scale"; then
                             resizeIcon "$icon" "$result" "$iconSize" "$scale"
                         fi
+                        foundIcon=OTHER
                         ;;
                     scalable)
                         synthesizeIcon "${scalableIcon[0]}" "$result" "$iconSize" "$scale" || true
+                        foundIcon=OTHER
+                        ;;
+                    fallback)
+                        # Use the largest size available to scale to
+                        # appropriate sizes.
+                        if [[ $foundIcon != OTHER ]]; then
+                          foundIcon=$icon
+                        fi
                         ;;
                     *)
                         ;;
                 esac
             done
         done
+        if [[ $foundIcon != NONE && $foundIcon != OTHER ]]; then
+            # Ideally we'd only resize to whatever the closest sizes are,
+            # starting from whatever icon sizes are available.
+            for iconSize in 16 32 128 256 512; do
+              local result=${resultdir}/${iconSize}x${iconSize}.png
+              resizeIcon "$foundIcon" "$result" "$iconSize" 1
+            done
+        fi
         echo "$resultdir"
     }
 
     iconsdir=$(getIcons "$sharePath" "apps/${iconName}" "$theme")
-    if [[ ! -z "$(ls -1 "$iconsdir/"*)" ]]; then
-        icnsutil compose "$out/${iconName}.icns" "$iconsdir/"*
+    if [[ -n "$(ls -1 "$iconsdir/"*)" ]]; then
+        icnsutil compose --toc "$out/${iconName}.icns" "$iconsdir/"*
     else
         echo "Warning: no icons were found. Creating an empty icon for ${iconName}.icns."
         touch "$out/${iconName}.icns"