From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/winemac.drv/dllmain.c | 168 ++++++++++++++++++++++++++++++++++ dlls/winemac.drv/image.c | 178 ++++++------------------------------- dlls/winemac.drv/unixlib.h | 25 +++++- 3 files changed, 219 insertions(+), 152 deletions(-)
diff --git a/dlls/winemac.drv/dllmain.c b/dlls/winemac.drv/dllmain.c index 675820b28cd..e281a473e07 100644 --- a/dlls/winemac.drv/dllmain.c +++ b/dlls/winemac.drv/dllmain.c @@ -63,6 +63,30 @@ static BOOL CALLBACK get_process_windows(HWND hwnd, LPARAM lp) return TRUE; }
+#include "pshpack1.h" + +typedef struct +{ + BYTE bWidth; + BYTE bHeight; + BYTE bColorCount; + BYTE bReserved; + WORD wPlanes; + WORD wBitCount; + DWORD dwBytesInRes; + WORD nID; +} GRPICONDIRENTRY; + +typedef struct +{ + WORD idReserved; + WORD idType; + WORD idCount; + GRPICONDIRENTRY idEntries[1]; +} GRPICONDIR; + +#include "poppack.h" + static void quit_reply(int reply) { struct quit_result_params params = { .result = reply }; @@ -199,9 +223,153 @@ fail: return 0; }
+/*********************************************************************** + * get_first_resource + * + * Helper for create_app_icon_images(). Enum proc for EnumResourceNamesW() + * which just gets the handle for the first resource and stops further + * enumeration. + */ +static BOOL CALLBACK get_first_resource(HMODULE module, LPCWSTR type, LPWSTR name, LONG_PTR lparam) +{ + HRSRC *res_info = (HRSRC*)lparam; + + *res_info = FindResourceW(module, name, (LPCWSTR)RT_GROUP_ICON); + return FALSE; +} + + +/*********************************************************************** + * macdrv_app_icon + */ +static NTSTATUS WINAPI macdrv_app_icon(void *arg, ULONG size) +{ + struct app_icon_params *params = arg; + struct app_icon_result *result = params->result; + HRSRC res_info; + HGLOBAL res_data; + GRPICONDIR *icon_dir; + int i; + + TRACE("()\n"); + + result->count = 0; + + res_info = NULL; + EnumResourceNamesW(NULL, (LPCWSTR)RT_GROUP_ICON, get_first_resource, (LONG_PTR)&res_info); + if (!res_info) + { + WARN("found no RT_GROUP_ICON resource\n"); + return 0; + } + + if (!(res_data = LoadResource(NULL, res_info))) + { + WARN("failed to load RT_GROUP_ICON resource\n"); + return 0; + } + + if (!(icon_dir = LockResource(res_data))) + { + WARN("failed to lock RT_GROUP_ICON resource\n"); + goto cleanup; + } + + for (i = 0; i < icon_dir->idCount && result->count < ARRAYSIZE(result->entries); i++) + { + struct app_icon_entry *entry = &result->entries[result->count]; + int width = icon_dir->idEntries[i].bWidth; + int height = icon_dir->idEntries[i].bHeight; + BOOL found_better_bpp = FALSE; + int j; + LPCWSTR name; + HGLOBAL icon_res_data; + BYTE *icon_bits; + + if (!width) width = 256; + if (!height) height = 256; + + /* If there's another icon at the same size but with better + color depth, skip this one. We end up making CGImages that + are all 32 bits per pixel, so Cocoa doesn't get the original + color depth info to pick the best representation itself. */ + for (j = 0; j < icon_dir->idCount; j++) + { + int jwidth = icon_dir->idEntries[j].bWidth; + int jheight = icon_dir->idEntries[j].bHeight; + + if (!jwidth) jwidth = 256; + if (!jheight) jheight = 256; + + if (j != i && jwidth == width && jheight == height && + icon_dir->idEntries[j].wBitCount > icon_dir->idEntries[i].wBitCount) + { + found_better_bpp = TRUE; + break; + } + } + + if (found_better_bpp) continue; + + name = MAKEINTRESOURCEW(icon_dir->idEntries[i].nID); + res_info = FindResourceW(NULL, name, (LPCWSTR)RT_ICON); + if (!res_info) + { + WARN("failed to find RT_ICON resource %d with ID %hd\n", i, icon_dir->idEntries[i].nID); + continue; + } + + icon_res_data = LoadResource(NULL, res_info); + if (!icon_res_data) + { + WARN("failed to load icon %d with ID %hd\n", i, icon_dir->idEntries[i].nID); + continue; + } + + icon_bits = LockResource(icon_res_data); + if (icon_bits) + { + static const BYTE png_magic[] = { 0x89, 0x50, 0x4e, 0x47 }; + + entry->width = width; + entry->height = height; + entry->size = icon_dir->idEntries[i].dwBytesInRes; + + if (!memcmp(icon_bits, png_magic, sizeof(png_magic))) + { + entry->png = icon_bits; + entry->icon = 0; + result->count++; + } + else + { + entry->icon = CreateIconFromResourceEx(icon_bits, icon_dir->idEntries[i].dwBytesInRes, + TRUE, 0x00030000, width, height, 0); + if (entry->icon) + { + entry->png = NULL; + result->count++; + } + else + WARN("failed to create icon %d from resource with ID %hd\n", i, icon_dir->idEntries[i].nID); + } + } + else + WARN("failed to lock RT_ICON resource %d with ID %hd\n", i, icon_dir->idEntries[i].nID); + + FreeResource(icon_res_data); + } + +cleanup: + FreeResource(res_data); + + return 0; +} + typedef NTSTATUS (WINAPI *kernel_callback)(void *params, ULONG size); static const kernel_callback kernel_callbacks[] = { + macdrv_app_icon, macdrv_app_quit_request, macdrv_dnd_query_drag, macdrv_dnd_query_drop, diff --git a/dlls/winemac.drv/image.c b/dlls/winemac.drv/image.c index 943ad97b749..f6423858136 100644 --- a/dlls/winemac.drv/image.c +++ b/dlls/winemac.drv/image.c @@ -25,30 +25,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(image);
-#include "pshpack1.h" - -typedef struct -{ - BYTE bWidth; - BYTE bHeight; - BYTE bColorCount; - BYTE bReserved; - WORD wPlanes; - WORD wBitCount; - DWORD dwBytesInRes; - WORD nID; -} GRPICONDIRENTRY; - -typedef struct -{ - WORD idReserved; - WORD idType; - WORD idCount; - GRPICONDIRENTRY idEntries[1]; -} GRPICONDIR; - -#include "poppack.h" -
/*********************************************************************** * create_cgimage_from_icon_bitmaps @@ -264,167 +240,67 @@ cleanup: }
-/*********************************************************************** - * get_first_resource - * - * Helper for create_app_icon_images(). Enum proc for EnumResourceNamesW() - * which just gets the handle for the first resource and stops further - * enumeration. - */ -static BOOL CALLBACK get_first_resource(HMODULE module, LPCWSTR type, LPWSTR name, LONG_PTR lparam) -{ - HRSRC *res_info = (HRSRC*)lparam; - - *res_info = FindResourceW(module, name, (LPCWSTR)RT_GROUP_ICON); - return FALSE; -} - - /*********************************************************************** * create_app_icon_images */ CFArrayRef create_app_icon_images(void) { - HRSRC res_info; - HGLOBAL res_data; - GRPICONDIR *icon_dir; + struct app_icon_result icons; + struct app_icon_params params = { .result = &icons }; CFMutableArrayRef images = NULL; int i;
TRACE("()\n");
- res_info = NULL; - EnumResourceNamesW(NULL, (LPCWSTR)RT_GROUP_ICON, get_first_resource, (LONG_PTR)&res_info); - if (!res_info) - { - WARN("found no RT_GROUP_ICON resource\n"); - return NULL; - } + macdrv_client_func(client_func_app_icon, ¶ms, sizeof(params));
- if (!(res_data = LoadResource(NULL, res_info))) - { - WARN("failed to load RT_GROUP_ICON resource\n"); - return NULL; - } + if (!icons.count) return NULL;
- if (!(icon_dir = LockResource(res_data))) - { - WARN("failed to lock RT_GROUP_ICON resource\n"); - goto cleanup; - } - - images = CFArrayCreateMutable(NULL, icon_dir->idCount, &kCFTypeArrayCallBacks); + images = CFArrayCreateMutable(NULL, icons.count, &kCFTypeArrayCallBacks); if (!images) { WARN("failed to create images array\n"); - goto cleanup; + return NULL; }
- for (i = 0; i < icon_dir->idCount; i++) + for (i = 0; i < icons.count; i++) { - int width = icon_dir->idEntries[i].bWidth; - int height = icon_dir->idEntries[i].bHeight; - BOOL found_better_bpp = FALSE; - int j; - LPCWSTR name; - HGLOBAL icon_res_data; - BYTE *icon_bits; - - if (!width) width = 256; - if (!height) height = 256; - - /* If there's another icon at the same size but with better - color depth, skip this one. We end up making CGImages that - are all 32 bits per pixel, so Cocoa doesn't get the original - color depth info to pick the best representation itself. */ - for (j = 0; j < icon_dir->idCount; j++) - { - int jwidth = icon_dir->idEntries[j].bWidth; - int jheight = icon_dir->idEntries[j].bHeight; - - if (!jwidth) jwidth = 256; - if (!jheight) jheight = 256; + struct app_icon_entry *icon = &icons.entries[i]; + CGImageRef cgimage = NULL;
- if (j != i && jwidth == width && jheight == height && - icon_dir->idEntries[j].wBitCount > icon_dir->idEntries[i].wBitCount) - { - found_better_bpp = TRUE; - break; - } - } - - if (found_better_bpp) continue; - - name = MAKEINTRESOURCEW(icon_dir->idEntries[i].nID); - res_info = FindResourceW(NULL, name, (LPCWSTR)RT_ICON); - if (!res_info) + if (icon->png) { - WARN("failed to find RT_ICON resource %d with ID %hd\n", i, icon_dir->idEntries[i].nID); - continue; - } - - icon_res_data = LoadResource(NULL, res_info); - if (!icon_res_data) - { - WARN("failed to load icon %d with ID %hd\n", i, icon_dir->idEntries[i].nID); - continue; - } - - icon_bits = LockResource(icon_res_data); - if (icon_bits) - { - static const BYTE png_magic[] = { 0x89, 0x50, 0x4e, 0x47 }; - CGImageRef cgimage = NULL; - - if (!memcmp(icon_bits, png_magic, sizeof(png_magic))) - { - CFDataRef data = CFDataCreate(NULL, (UInt8*)icon_bits, icon_dir->idEntries[i].dwBytesInRes); - if (data) - { - CGDataProviderRef provider = CGDataProviderCreateWithCFData(data); - CFRelease(data); - if (provider) - { - cgimage = CGImageCreateWithPNGDataProvider(provider, NULL, FALSE, - kCGRenderingIntentDefault); - CGDataProviderRelease(provider); - } - } - } - - if (!cgimage) + CFDataRef data = CFDataCreate(NULL, icon->png, icon->size); + if (data) { - HICON icon; - icon = CreateIconFromResourceEx(icon_bits, icon_dir->idEntries[i].dwBytesInRes, - TRUE, 0x00030000, width, height, 0); - if (icon) + CGDataProviderRef provider = CGDataProviderCreateWithCFData(data); + CFRelease(data); + if (provider) { - cgimage = create_cgimage_from_icon(icon, width, height); - DestroyIcon(icon); + cgimage = CGImageCreateWithPNGDataProvider(provider, NULL, FALSE, + kCGRenderingIntentDefault); + CGDataProviderRelease(provider); } - else - WARN("failed to create icon %d from resource with ID %hd\n", i, icon_dir->idEntries[i].nID); - } - - if (cgimage) - { - CFArrayAppendValue(images, cgimage); - CGImageRelease(cgimage); } } else - WARN("failed to lock RT_ICON resource %d with ID %hd\n", i, icon_dir->idEntries[i].nID); + { + cgimage = create_cgimage_from_icon(icon->icon, icon->width, icon->height); + NtUserDestroyCursor(icon->icon, 0); + }
- FreeResource(icon_res_data); + if (cgimage) + { + CFArrayAppendValue(images, cgimage); + CGImageRelease(cgimage); + } }
-cleanup: if (images && !CFArrayGetCount(images)) { CFRelease(images); images = NULL; } - FreeResource(res_data);
return images; } diff --git a/dlls/winemac.drv/unixlib.h b/dlls/winemac.drv/unixlib.h index 894ab699c13..fea59564b92 100644 --- a/dlls/winemac.drv/unixlib.h +++ b/dlls/winemac.drv/unixlib.h @@ -102,7 +102,8 @@ struct quit_result_params /* driver client callbacks exposed with KernelCallbackTable interface */ enum macdrv_client_funcs { - client_func_app_quit_request = NtUserDriverCallbackFirst, + client_func_app_icon = NtUserDriverCallbackFirst, + client_func_app_quit_request, client_func_dnd_query_drag, client_func_dnd_query_drop, client_func_dnd_query_exited, @@ -111,6 +112,28 @@ enum macdrv_client_funcs client_func_last };
+/* macdrv_app_icon result */ +struct app_icon_entry +{ + UINT32 width; + UINT32 height; + UINT32 size; + void *png; + HICON icon; +}; + +struct app_icon_result +{ + UINT32 count; + struct app_icon_entry entries[64]; +}; + +/* macdrv_app_icon params */ +struct app_icon_params +{ + struct app_icon_result *result; /* FIXME: Use NtCallbackReturn instead */ +}; + /* macdrv_app_quit_request params */ struct app_quit_request_params {