Commit 76e7fcc9 authored by Alexandre Julliard's avatar Alexandre Julliard

user32: Store icon objects directly in the cache instead of using a separate structure.

parent 76cd25c8
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "config.h" #include "config.h"
#include "wine/port.h" #include "wine/port.h"
#include <assert.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -37,6 +38,7 @@ ...@@ -37,6 +38,7 @@
#include "wine/exception.h" #include "wine/exception.h"
#include "wine/server.h" #include "wine/server.h"
#include "controls.h" #include "controls.h"
#include "win.h"
#include "user_private.h" #include "user_private.h"
#include "wine/list.h" #include "wine/list.h"
#include "wine/unicode.h" #include "wine/unicode.h"
...@@ -75,31 +77,8 @@ static HDC screen_dc; ...@@ -75,31 +77,8 @@ static HDC screen_dc;
static const WCHAR DISPLAYW[] = {'D','I','S','P','L','A','Y',0}; static const WCHAR DISPLAYW[] = {'D','I','S','P','L','A','Y',0};
/**********************************************************************
* ICONCACHE for cursors/icons loaded with LR_SHARED.
*/
typedef struct tagICONCACHE
{
struct list entry;
HMODULE hModule;
HRSRC hRsrc;
HRSRC hGroupRsrc;
HICON hIcon;
} ICONCACHE;
static struct list icon_cache = LIST_INIT( icon_cache ); static struct list icon_cache = LIST_INIT( icon_cache );
static CRITICAL_SECTION IconCrst;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &IconCrst,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": IconCrst") }
};
static CRITICAL_SECTION IconCrst = { &critsect_debug, -1, 0, 0, 0, 0 };
/********************************************************************** /**********************************************************************
* User objects management * User objects management
*/ */
...@@ -114,9 +93,11 @@ struct cursoricon_frame ...@@ -114,9 +93,11 @@ struct cursoricon_frame
struct cursoricon_object struct cursoricon_object
{ {
struct user_object obj; /* object header */ struct user_object obj; /* object header */
struct list entry; /* entry in shared icons list */
ULONG_PTR param; /* opaque param used by 16-bit code */ ULONG_PTR param; /* opaque param used by 16-bit code */
HMODULE module; /* module for icons loaded from resources */ HMODULE module; /* module for icons loaded from resources */
LPWSTR resname; /* resource name for icons loaded from resources */ LPWSTR resname; /* resource name for icons loaded from resources */
HRSRC rsrc; /* resource for shared icons */
BOOL is_icon; /* whether icon or cursor */ BOOL is_icon; /* whether icon or cursor */
UINT width; UINT width;
UINT height; UINT height;
...@@ -162,6 +143,8 @@ static BOOL free_icon_handle( HICON handle ) ...@@ -162,6 +143,8 @@ static BOOL free_icon_handle( HICON handle )
ULONG_PTR param = obj->param; ULONG_PTR param = obj->param;
UINT i; UINT i;
assert( !obj->rsrc ); /* shared icons can't be freed */
for (i=0; i<obj->num_frames; i++) for (i=0; i<obj->num_frames; i++)
{ {
if (obj->frames[i].alpha) DeleteObject( obj->frames[i].alpha ); if (obj->frames[i].alpha) DeleteObject( obj->frames[i].alpha );
...@@ -401,77 +384,19 @@ static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width, ...@@ -401,77 +384,19 @@ static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
} }
/********************************************************************** /**********************************************************************
* CURSORICON_FindSharedIcon * is_icon_shared
*/
static HICON CURSORICON_FindSharedIcon( HMODULE hModule, HRSRC hRsrc )
{
HICON hIcon = 0;
ICONCACHE *ptr;
EnterCriticalSection( &IconCrst );
LIST_FOR_EACH_ENTRY( ptr, &icon_cache, ICONCACHE, entry )
if ( ptr->hModule == hModule && ptr->hRsrc == hRsrc )
{
hIcon = ptr->hIcon;
break;
}
LeaveCriticalSection( &IconCrst );
return hIcon;
}
/*************************************************************************
* CURSORICON_FindCache
*
* Given a handle, find the corresponding cache element
*
* PARAMS
* Handle [I] handle to an Image
*
* RETURNS
* Success: The cache entry
* Failure: NULL
*
*/ */
static ICONCACHE* CURSORICON_FindCache(HICON hIcon) static BOOL is_icon_shared( HICON handle )
{ {
ICONCACHE *ptr; struct cursoricon_object *info;
ICONCACHE *pRet=NULL; BOOL ret = FALSE;
EnterCriticalSection( &IconCrst );
LIST_FOR_EACH_ENTRY( ptr, &icon_cache, ICONCACHE, entry ) if ((info = get_icon_ptr( handle )))
{ {
if ( hIcon == ptr->hIcon ) ret = info->rsrc != NULL;
{ release_icon_ptr( handle, info );
pRet = ptr;
break;
}
} }
return ret;
LeaveCriticalSection( &IconCrst );
return pRet;
}
/**********************************************************************
* CURSORICON_AddSharedIcon
*/
static void CURSORICON_AddSharedIcon( HMODULE hModule, HRSRC hRsrc, HRSRC hGroupRsrc, HICON hIcon )
{
ICONCACHE *ptr = HeapAlloc( GetProcessHeap(), 0, sizeof(ICONCACHE) );
if ( !ptr ) return;
ptr->hModule = hModule;
ptr->hRsrc = hRsrc;
ptr->hIcon = hIcon;
ptr->hGroupRsrc = hGroupRsrc;
EnterCriticalSection( &IconCrst );
list_add_head( &icon_cache, &ptr->entry );
LeaveCriticalSection( &IconCrst );
} }
/********************************************************************** /**********************************************************************
...@@ -849,7 +774,7 @@ done: ...@@ -849,7 +774,7 @@ done:
return ret; return ret;
} }
static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, HMODULE module, LPCWSTR resname, static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, HMODULE module, LPCWSTR resname, HRSRC rsrc,
POINT hotspot, BOOL bIcon, INT width, INT height, UINT cFlag ) POINT hotspot, BOOL bIcon, INT width, INT height, UINT cFlag )
{ {
HICON hObj; HICON hObj;
...@@ -908,6 +833,11 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, HMODULE module, LPCW ...@@ -908,6 +833,11 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, HMODULE module, LPCW
} }
else info->resname = MAKEINTRESOURCEW( LOWORD(resname) ); else info->resname = MAKEINTRESOURCEW( LOWORD(resname) );
if (module && (cFlag & LR_SHARED))
{
info->rsrc = rsrc;
list_add_head( &icon_cache, &info->entry );
}
release_icon_ptr( hObj, info ); release_icon_ptr( hObj, info );
USER_Driver->pCreateCursorIcon( hObj ); USER_Driver->pCreateCursorIcon( hObj );
} }
...@@ -1180,7 +1110,7 @@ HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize, ...@@ -1180,7 +1110,7 @@ HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
bmi = (BITMAPINFO *)(pt + 2); bmi = (BITMAPINFO *)(pt + 2);
} }
return CURSORICON_CreateIconFromBMI( bmi, NULL, NULL, hotspot, bIcon, width, height, cFlag ); return CURSORICON_CreateIconFromBMI( bmi, NULL, NULL, NULL, hotspot, bIcon, width, height, cFlag );
} }
...@@ -1242,7 +1172,7 @@ static HICON CURSORICON_LoadFromFile( LPCWSTR filename, ...@@ -1242,7 +1172,7 @@ static HICON CURSORICON_LoadFromFile( LPCWSTR filename,
hotspot.x = entry->xHotspot; hotspot.x = entry->xHotspot;
hotspot.y = entry->yHotspot; hotspot.y = entry->yHotspot;
hIcon = CURSORICON_CreateIconFromBMI( (BITMAPINFO *)&bits[entry->dwDIBOffset], NULL, NULL, hIcon = CURSORICON_CreateIconFromBMI( (BITMAPINFO *)&bits[entry->dwDIBOffset], NULL, NULL, NULL,
hotspot, !fCursor, width, height, loadflags ); hotspot, !fCursor, width, height, loadflags );
end: end:
TRACE("loaded %s -> %p\n", debugstr_w( filename ), hIcon ); TRACE("loaded %s -> %p\n", debugstr_w( filename ), hIcon );
...@@ -1261,7 +1191,7 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name, ...@@ -1261,7 +1191,7 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
{ {
HANDLE handle = 0; HANDLE handle = 0;
HICON hIcon = 0; HICON hIcon = 0;
HRSRC hRsrc, hGroupRsrc; HRSRC hRsrc;
CURSORICONDIR *dir; CURSORICONDIR *dir;
CURSORICONDIRENTRY *dirEntry; CURSORICONDIRENTRY *dirEntry;
LPBYTE bits; LPBYTE bits;
...@@ -1285,7 +1215,6 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name, ...@@ -1285,7 +1215,6 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
if (!(hRsrc = FindResourceW( hInstance, name, if (!(hRsrc = FindResourceW( hInstance, name,
(LPWSTR)(fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON) ))) (LPWSTR)(fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON) )))
return 0; return 0;
hGroupRsrc = hRsrc;
/* Find the best entry in the directory */ /* Find the best entry in the directory */
...@@ -1306,9 +1235,21 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name, ...@@ -1306,9 +1235,21 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
(LPWSTR)(fCursor ? RT_CURSOR : RT_ICON) ))) return 0; (LPWSTR)(fCursor ? RT_CURSOR : RT_ICON) ))) return 0;
/* If shared icon, check whether it was already loaded */ /* If shared icon, check whether it was already loaded */
if ( (loadflags & LR_SHARED) if (loadflags & LR_SHARED)
&& (hIcon = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 ) {
return hIcon; struct cursoricon_object *ptr;
USER_Lock();
LIST_FOR_EACH_ENTRY( ptr, &icon_cache, struct cursoricon_object, entry )
{
if (ptr->module != hInstance) continue;
if (ptr->rsrc != hRsrc) continue;
hIcon = ptr->obj.handle;
break;
}
USER_Unlock();
if (hIcon) return hIcon;
}
if (!(handle = LoadResource( hInstance, hRsrc ))) return 0; if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
bits = LockResource( handle ); bits = LockResource( handle );
...@@ -1325,15 +1266,9 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name, ...@@ -1325,15 +1266,9 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
hotspot.y = pt[1]; hotspot.y = pt[1];
bits += 2 * sizeof(SHORT); bits += 2 * sizeof(SHORT);
} }
hIcon = CURSORICON_CreateIconFromBMI( (BITMAPINFO *)bits, hInstance, name, hotspot, hIcon = CURSORICON_CreateIconFromBMI( (BITMAPINFO *)bits, hInstance, name, hRsrc,
!fCursor, width, height, loadflags ); hotspot, !fCursor, width, height, loadflags );
FreeResource( handle ); FreeResource( handle );
/* If shared icon, add to icon cache */
if ( hIcon && (loadflags & LR_SHARED) )
CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, hIcon );
return hIcon; return hIcon;
} }
...@@ -1447,7 +1382,7 @@ BOOL WINAPI DestroyIcon( HICON hIcon ) ...@@ -1447,7 +1382,7 @@ BOOL WINAPI DestroyIcon( HICON hIcon )
{ {
TRACE_(icon)("%p\n", hIcon ); TRACE_(icon)("%p\n", hIcon );
if (!CURSORICON_FindCache( hIcon )) free_icon_handle( hIcon ); if (!is_icon_shared( hIcon )) free_icon_handle( hIcon );
return TRUE; return TRUE;
} }
...@@ -2591,7 +2526,7 @@ HANDLE WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx, ...@@ -2591,7 +2526,7 @@ HANDLE WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
if (!(icon = get_icon_ptr( hnd ))) return 0; if (!(icon = get_icon_ptr( hnd ))) return 0;
if (icon->module && (flags & LR_COPYFROMRESOURCE)) if (icon->rsrc && (flags & LR_COPYFROMRESOURCE))
res = CURSORICON_Load( icon->module, icon->resname, desiredx, desiredy, depth, res = CURSORICON_Load( icon->module, icon->resname, desiredx, desiredy, depth,
type == IMAGE_CURSOR, flags ); type == IMAGE_CURSOR, flags );
else else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment