[10/10] winemenubuilder: Put appbundle icon inside the bundle.

Per Johansson per at morth.org
Sun Mar 17 12:18:42 CDT 2013


Move extract_icon to after the main link creation, and let the
platform link code modify the icon path to be inside the bundle.
---
 programs/winemenubuilder/appbundle.c       |  43 ++++++++---
 programs/winemenubuilder/winemenubuilder.c | 114 ++++++++++++++---------------
 programs/winemenubuilder/winemenubuilder.h |   6 +-
 programs/winemenubuilder/xdg.c             |  14 ++--
 4 files changed, 100 insertions(+), 77 deletions(-)

diff --git a/programs/winemenubuilder/appbundle.c b/programs/winemenubuilder/appbundle.c
index 57e9b9d..80ff3c9 100644
--- a/programs/winemenubuilder/appbundle.c
+++ b/programs/winemenubuilder/appbundle.c
@@ -155,7 +155,7 @@ HRESULT osx_write_icon(IStream *icoStream, int exeIndex, LPCWSTR icoPathW, const
         }
     }
 
-    icnsPath = heap_printf("/tmp/%s.icns", destFilename);
+    icnsPath = heap_printf("%s.icns", destFilename);
     if (icnsPath == NULL)
     {
         hr = E_OUTOFMEMORY;
@@ -217,7 +217,7 @@ static BOOL generate_bundle_script(const char *file, const char *path,
     return TRUE;
 }
 
-CFDictionaryRef create_info_plist_dictionary(const char *link_name)
+CFDictionaryRef create_info_plist_dictionary(const char *link_name, const char *icon)
 {
     CFMutableDictionaryRef dict = NULL;
     CFStringRef namestr;
@@ -246,6 +246,17 @@ CFDictionaryRef create_info_plist_dictionary(const char *link_name)
     CFDictionarySetValue( dict, CFSTR("CFBundlePackageType"), CFSTR("APPL") );
     CFDictionarySetValue( dict, CFSTR("CFBundleVersion"), CFSTR("1.0") );
 
+    if (icon)
+    {
+        CFStringRef iconstr = CFStringCreateWithCString(NULL, icon, CFStringGetSystemEncoding());
+
+        if (iconstr)
+        {
+            CFDictionarySetValue( dict, CFSTR("CFBundleIconFile"), iconstr );
+            CFRelease(iconstr);
+        }
+    }
+
 cleanup:
     if (namestr)
         CFRelease(namestr);
@@ -296,10 +307,10 @@ cleanup:
     return ret;
 }
 
-BOOL build_app_bundle(const char *unix_link, const char *dir, const char *link, const char *link_name, const char *path, const char *args, const char *workdir, const char *icon)
+BOOL build_app_bundle(const char *unix_link, const char *dir, const char *link, const char *link_name, const char *path, const char *args, const char *workdir, char **icon)
 {
     BOOL ret = FALSE;
-    char *path_to_bundle, *path_to_macos, *path_to_script, *path_to_info;
+    char *path_to_bundle, *path_to_macos, *path_to_script, *path_to_info, *path_to_resources;
     CFDictionaryRef info = NULL;
 
     path_to_bundle = heap_printf("%s/%s.app", dir, link);
@@ -308,22 +319,33 @@ BOOL build_app_bundle(const char *unix_link, const char *dir, const char *link,
     path_to_macos = heap_printf("%s/Contents/MacOS", path_to_bundle);
     path_to_script = heap_printf("%s/Contents/MacOS/winelauncher", path_to_bundle);
     path_to_info = heap_printf("%s/Contents/Info.plist", path_to_bundle);
-    if (!path_to_macos || !path_to_script || !path_to_info)
+    path_to_resources = heap_printf("%s/Contents/Resources", path_to_bundle);
+    if (!path_to_macos || !path_to_script || !path_to_info || !path_to_resources)
         goto out;
 
-    if (!create_directories(path_to_macos))
+    if (!create_directories(path_to_macos) || !create_directories(path_to_resources))
         goto out;
 
     if (!generate_bundle_script(path_to_script, path, args, workdir))
         goto out;
 
-    info = create_info_plist_dictionary(link_name);
+    info = create_info_plist_dictionary(link_name, *icon);
     if (!info)
         goto out;
 
     if (!write_property_list(path_to_info, info, kCFPropertyListXMLFormat_v1_0))
         goto out;
 
+    if (*icon)
+    {
+        char *tmp = heap_printf("%s/%s", path_to_resources, *icon);
+
+        if (!tmp)
+            goto out;
+        HeapFree(GetProcessHeap(), 0, *icon);
+        *icon = tmp;
+    }
+
     if (unix_link)
     {
         DWORD r = register_menus_entry(path_to_bundle, unix_link);
@@ -340,19 +362,20 @@ out:
     HeapFree(GetProcessHeap(), 0, path_to_macos);
     HeapFree(GetProcessHeap(), 0, path_to_script);
     HeapFree(GetProcessHeap(), 0, path_to_info);
+    HeapFree(GetProcessHeap(), 0, path_to_resources);
     if (info)
         CFRelease(info);
     return ret;
 }
 
 int appbundle_build_desktop_link(const char *unix_link, const char *link, const char *link_name, const char *path,
-        const char *args, const char *descr, const char *workdir, char *icon)
+        const char *args, const char *descr, const char *workdir, char **icon)
 {
     return !build_app_bundle(unix_link, mac_desktop_dir, link_name, link_name, path, args, workdir, icon);
 }
 
 int appbundle_build_menu_link(const char *unix_link, const char *link, const char *link_name, const char *path,
-        const char *args, const char *descr, const char *workdir, char *icon)
+        const char *args, const char *descr, const char *workdir, char **icon)
 {
     return !build_app_bundle(unix_link, wine_applications_dir, link, link_name, path, args, workdir, icon);
 }
@@ -376,7 +399,7 @@ BOOL appbundle_write_mime_type_entry(void *user, const char *extensionA, const c
 
 BOOL appbundle_write_association_entry(void *user, const char *extensionA, const char *friendlyAppNameA,
         const char *friendlyDocNameA, const char *mimeTypeA, const char *progIdA,
-        const char *appIconA)
+        char **appIconA, char **docIconA)
 {
     return FALSE;
 }
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index c3e308d..e8645d9 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -1835,21 +1835,7 @@ static BOOL generate_associations(void *user)
                      * and the default name is more intuitive anyway.
                      */
                     if (iconW)
-                    {
                         iconA = slashes_to_minuses(mimeTypeA);
-                        if (iconA)
-                        {
-                            int index = 0;
-                            WCHAR *comma = strrchrW(iconW, ',');
-                            if (comma)
-                            {
-                                *comma = 0;
-                                index = atoiW(comma + 1);
-                            }
-                            extract_icon(iconW, index, iconA, FALSE);
-                        }
-                    }
-
                     wmb_dispatch->write_mime_type_entry(user, extensionA, mimeTypeA, friendlyDocNameA);
                     hasChanged = TRUE;
                 }
@@ -1867,11 +1853,7 @@ static BOOL generate_associations(void *user)
 
             executableW = assoc_query(ASSOCSTR_EXECUTABLE, extensionW, openW);
             if (executableW)
-            {
                 openWithIconA = compute_native_identifier(0, executableW);
-                if (openWithIconA)
-                    extract_icon(executableW, 0, openWithIconA, FALSE);
-            }
 
             friendlyAppNameW = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, extensionW, openW);
             if (friendlyAppNameW)
@@ -1932,11 +1914,25 @@ static BOOL generate_associations(void *user)
 
             if (has_association_changed(extensionW, mimeTypeA, progIdW, friendlyAppNameA, openWithIconA))
             {
-                if (wmb_dispatch->write_association_entry(user, extensionA, friendlyAppNameA, friendlyDocNameA, mimeTypeA, progIdA, openWithIconA))
+                if (wmb_dispatch->write_association_entry(user, extensionA, friendlyAppNameA, friendlyDocNameA, mimeTypeA, progIdA, &openWithIconA, &iconA))
                 {
                     hasChanged = TRUE;
                     update_association(extensionW, mimeTypeA, progIdW, friendlyAppNameA, openWithIconA);
                 }
+
+                if (openWithIconA)
+                    extract_icon(executableW, 0, openWithIconA, FALSE);
+                if (iconA)
+                {
+                    int index = 0;
+                    WCHAR *comma = strrchrW(iconW, ',');
+                    if (comma)
+                    {
+                        *comma = 0;
+                        index = atoiW(comma + 1);
+                    }
+                    extract_icon(iconW, index, iconA, FALSE);
+                }
             }
 
         end:
@@ -2053,23 +2049,8 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
             WINE_TRACE("pidl path  : %s\n", wine_dbgstr_w(szPath));
     }
 
-    /* extract the icon */
+    /* get icon name */
     icon_name = compute_native_identifier(iIconId, szIconPath ? szIconPath : szPath);
-    if (icon_name)
-        r = extract_icon(szIconPath ? szIconPath : szPath, iIconId, icon_name, bWait);
-    else
-        r = E_OUTOFMEMORY;
-    /* fail - try once again after parent process exit */
-    if( FAILED(r) )
-    {
-        if (bWait)
-        {
-            WINE_WARN("Unable to extract icon, deferring.\n");
-            goto cleanup;
-        }
-        WINE_ERR("failed to extract icon from %s\n",
-                 wine_dbgstr_w( szIconPath[0] ? szIconPath : szPath ));
-    }
 
     unix_link = wine_get_unix_file_name(link);
     if (unix_link == NULL)
@@ -2159,13 +2140,13 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
             if (link_arg)
             {
                 r = wmb_dispatch->build_desktop_link(unix_link, link_name, lastEntry,
-                        start_path, link_arg, description, work_dir, icon_name);
+                        start_path, link_arg, description, work_dir, &icon_name);
                 HeapFree(GetProcessHeap(), 0, link_arg);
             }
         }
         else
         {
-            r = wmb_dispatch->build_desktop_link(NULL, link_name, lastEntry, escaped_path, escaped_args, description, work_dir, icon_name);
+            r = wmb_dispatch->build_desktop_link(NULL, link_name, lastEntry, escaped_path, escaped_args, description, work_dir, &icon_name);
         }
     }
     else
@@ -2173,11 +2154,30 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
         char *link_arg = escape_unix_link_arg(unix_link);
         if (link_arg)
         {
-            r = wmb_dispatch->build_menu_link(unix_link, link_name, lastEntry, start_path, link_arg, description, work_dir, icon_name);
+            r = wmb_dispatch->build_menu_link(unix_link, link_name, lastEntry, start_path, link_arg, description, work_dir, &icon_name);
             HeapFree(GetProcessHeap(), 0, link_arg);
         }
     }
 
+    /* extract the icon */
+    if( szIconPath[0] )
+        r = extract_icon( szIconPath , iIconId, icon_name, bWait );
+    else
+        r = extract_icon( szPath, iIconId, icon_name, bWait );
+
+    /* fail - try once again after parent process exit */
+    if( FAILED(r) )
+    {
+        if (bWait)
+        {
+            WINE_WARN("Unable to extract icon, deferring.\n");
+            goto cleanup;
+        }
+        WINE_ERR("failed to extract icon from %s\n",
+                 wine_dbgstr_w( szIconPath[0] ? szIconPath : szPath ));
+        r = 0; /* Not fatal */
+    }
+
     ReleaseSemaphore( hsem, 1, NULL );
 
 cleanup:
@@ -2292,23 +2292,6 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
         IPropertySetStorage_Release(pPropSetStg);
     }
 
-    if( icon_name )
-    {
-        r = extract_icon( pv[0].u.pwszVal, pv[1].u.iVal, icon_name, bWait );
-	/* fail - try once again after parent process exit */
-        if (FAILED(r))
-        {
-            if (bWait)
-            {
-                WINE_WARN("Unable to extract icon, deferring.\n");
-                ret = FALSE;
-                goto cleanup;
-            }
-            WINE_ERR("failed to extract icon from %s\n",
-                     wine_dbgstr_w( pv[0].u.pwszVal ));
-        }
-    }
-
     hSem = CreateSemaphoreA( NULL, 1, 1, "winemenubuilder_semaphore");
     if( WAIT_OBJECT_0 != MsgWaitForMultipleObjects( 1, &hSem, FALSE, INFINITE, QS_ALLINPUT ) )
     {
@@ -2321,12 +2304,29 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
     else
         ++lastEntry;
     if (in_desktop_dir(csidl))
-        r = wmb_dispatch->build_desktop_link(NULL, link_name, lastEntry, start_path, escaped_urlPath, NULL, NULL, icon_name);
+        r = wmb_dispatch->build_desktop_link(NULL, link_name, lastEntry, start_path, escaped_urlPath, NULL, NULL, &icon_name);
     else
-        r = wmb_dispatch->build_menu_link(unix_link, link_name, lastEntry, start_path, escaped_urlPath, NULL, NULL, icon_name);
+        r = wmb_dispatch->build_menu_link(unix_link, link_name, lastEntry, start_path, escaped_urlPath, NULL, NULL, &icon_name);
     ret = (r == 0);
     ReleaseSemaphore(hSem, 1, NULL);
 
+    if (ret && icon_name)
+    {
+        r = extract_icon( pv[0].u.pwszVal, pv[1].u.iVal, icon_name, bWait );
+        /* fail - try once again after parent process exit */
+        if( FAILED(r) )
+        {
+            if (bWait)
+            {
+                WINE_WARN("Unable to extract icon, deferring.\n");
+                ret = FALSE;
+                goto cleanup;
+            }
+            WINE_ERR("failed to extract icon from %s\n",
+                     wine_dbgstr_w( pv[0].u.pwszVal ));
+        }
+    }
+
 cleanup:
     if (hSem)
         CloseHandle(hSem);
diff --git a/programs/winemenubuilder/winemenubuilder.h b/programs/winemenubuilder/winemenubuilder.h
index 0568b70..4d17fa6 100644
--- a/programs/winemenubuilder/winemenubuilder.h
+++ b/programs/winemenubuilder/winemenubuilder.h
@@ -53,9 +53,9 @@ struct winemenubuilder_dispatch
     BOOL (*init)(void);
 
     int (*build_desktop_link)(const char *unix_link, const char *link, const char *link_name, const char *path,
-            const char *args, const char *descr, const char *workdir, char *icon);
+            const char *args, const char *descr, const char *workdir, char **icon);
     int (*build_menu_link)(const char *unix_link, const char *link, const char *link_name, const char *path,
-            const char *args, const char *descr, const char *workdir, char *icon);
+            const char *args, const char *descr, const char *workdir, char **icon);
 
     HRESULT (*write_icon)(IStream *icoStream, int exeIndex, LPCWSTR icoPathW, const char *destFilename);
 
@@ -65,7 +65,7 @@ struct winemenubuilder_dispatch
     BOOL (*write_mime_type_entry)(void *user, const char *extensionA, const char *mimeTypeA, const char *friendlyDocNameA);
     BOOL (*write_association_entry)(void *user, const char *extensionA, const char *friendlyAppNameA,
             const char *friendlyDocNameA, const char *mimeTypeA, const char *progIdA,
-            const char *appIconA);
+            char **appIconA, char **iconA);
     BOOL (*remove_file_type_association)(void *user, const char *extensionA, LPCWSTR extensionW);
     void (*refresh_file_type_associations_cleanup)(void *user, BOOL hasChanged);
 };
diff --git a/programs/winemenubuilder/xdg.c b/programs/winemenubuilder/xdg.c
index 1b8e469..decfa0e 100644
--- a/programs/winemenubuilder/xdg.c
+++ b/programs/winemenubuilder/xdg.c
@@ -725,7 +725,7 @@ static BOOL write_freedesktop_association_entry(void *user, const char *dot_exte
                                                 const char *friendlyAppName,
                                                 const char *friendlyDocNameA,
                                                 const char *mimeType, const char *progId,
-                                                const char *openWithIcon)
+                                                char **openWithIcon, char **documentIcon)
 {
     struct xdg_file_type_user_data *ud = user;
     BOOL ret = FALSE;
@@ -739,7 +739,7 @@ static BOOL write_freedesktop_association_entry(void *user, const char *dot_exte
 
     WINE_TRACE("writing association for file type %s, friendlyAppName=%s, MIME type %s, progID=%s, icon=%s to file %s\n",
                wine_dbgstr_a(dot_extension), wine_dbgstr_a(friendlyAppName), wine_dbgstr_a(mimeType),
-               wine_dbgstr_a(progId), wine_dbgstr_a(openWithIcon), wine_dbgstr_a(desktopPath));
+               wine_dbgstr_a(progId), wine_dbgstr_a(*openWithIcon), wine_dbgstr_a(desktopPath));
 
     desktop = fopen(desktopPath, "w");
     if (desktop)
@@ -752,7 +752,7 @@ static BOOL write_freedesktop_association_entry(void *user, const char *dot_exte
         fprintf(desktop, "NoDisplay=true\n");
         fprintf(desktop, "StartupNotify=true\n");
         if (openWithIcon)
-            fprintf(desktop, "Icon=%s\n", openWithIcon);
+            fprintf(desktop, "Icon=%s\n", *openWithIcon);
         ret = TRUE;
         fclose(desktop);
     }
@@ -803,7 +803,7 @@ static BOOL init_xdg(void)
 }
 
 int xdg_build_desktop_link(const char *unix_link, const char *link, const char *link_name, const char *path,
-                                const char *args, const char *descr, const char *workdir, char *icon)
+                                const char *args, const char *descr, const char *workdir, char **icon)
 {
     char *location;
     int r = -1;
@@ -812,7 +812,7 @@ int xdg_build_desktop_link(const char *unix_link, const char *link, const char *
     if (location)
     {
         r = !write_desktop_entry(unix_link, location, link_name,
-                path, args, descr, workdir, icon);
+                path, args, descr, workdir, *icon);
         if (r == 0)
             chmod(location, 0755);
     }
@@ -820,9 +820,9 @@ int xdg_build_desktop_link(const char *unix_link, const char *link, const char *
 }
 
 int xdg_build_menu_link(const char *unix_link, const char *link, const char *link_name, const char *path,
-                             const char *args, const char *descr, const char *workdir, char *icon)
+                             const char *args, const char *descr, const char *workdir, char **icon)
 {
-    return !write_menu_entry(unix_link, link, path, args, descr, workdir, icon);
+    return !write_menu_entry(unix_link, link, path, args, descr, workdir, *icon);
 }
 
 void *xdg_refresh_file_type_associations_init(void)
-- 
1.8.0.2




More information about the wine-patches mailing list