[PATCH 07/11] winemac: Use unixlib interface for macdrv_app_icon.
Jacek Caban
wine at gitlab.winehq.org
Thu Jun 2 19:51:22 CDT 2022
From: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Jacek Caban <jacek at 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
{
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/177
More information about the wine-devel
mailing list