[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