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

This commit is contained in:
Alexandre Julliard 2010-10-11 14:55:46 +02:00
parent 76cd25c875
commit 76e7fcc9d8
1 changed files with 42 additions and 107 deletions

View File

@ -25,6 +25,7 @@
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
@ -37,6 +38,7 @@
#include "wine/exception.h"
#include "wine/server.h"
#include "controls.h"
#include "win.h"
#include "user_private.h"
#include "wine/list.h"
#include "wine/unicode.h"
@ -75,31 +77,8 @@ static HDC screen_dc;
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 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
*/
@ -114,9 +93,11 @@ struct cursoricon_frame
struct cursoricon_object
{
struct user_object obj; /* object header */
struct list entry; /* entry in shared icons list */
ULONG_PTR param; /* opaque param used by 16-bit code */
HMODULE module; /* module 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 */
UINT width;
UINT height;
@ -162,6 +143,8 @@ static BOOL free_icon_handle( HICON handle )
ULONG_PTR param = obj->param;
UINT i;
assert( !obj->rsrc ); /* shared icons can't be freed */
for (i=0; i<obj->num_frames; i++)
{
if (obj->frames[i].alpha) DeleteObject( obj->frames[i].alpha );
@ -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 )
static BOOL is_icon_shared( HICON handle )
{
HICON hIcon = 0;
ICONCACHE *ptr;
struct cursoricon_object *info;
BOOL ret = FALSE;
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)
{
ICONCACHE *ptr;
ICONCACHE *pRet=NULL;
EnterCriticalSection( &IconCrst );
LIST_FOR_EACH_ENTRY( ptr, &icon_cache, ICONCACHE, entry )
if ((info = get_icon_ptr( handle )))
{
if ( hIcon == ptr->hIcon )
{
pRet = ptr;
break;
}
ret = info->rsrc != NULL;
release_icon_ptr( handle, info );
}
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 );
return ret;
}
/**********************************************************************
@ -849,7 +774,7 @@ done:
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 )
{
HICON hObj;
@ -908,6 +833,11 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, HMODULE module, LPCW
}
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 );
USER_Driver->pCreateCursorIcon( hObj );
}
@ -1180,7 +1110,7 @@ HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
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,
hotspot.x = entry->xHotspot;
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 );
end:
TRACE("loaded %s -> %p\n", debugstr_w( filename ), hIcon );
@ -1261,7 +1191,7 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
{
HANDLE handle = 0;
HICON hIcon = 0;
HRSRC hRsrc, hGroupRsrc;
HRSRC hRsrc;
CURSORICONDIR *dir;
CURSORICONDIRENTRY *dirEntry;
LPBYTE bits;
@ -1285,7 +1215,6 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
if (!(hRsrc = FindResourceW( hInstance, name,
(LPWSTR)(fCursor ? RT_GROUP_CURSOR : RT_GROUP_ICON) )))
return 0;
hGroupRsrc = hRsrc;
/* Find the best entry in the directory */
@ -1306,9 +1235,21 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
(LPWSTR)(fCursor ? RT_CURSOR : RT_ICON) ))) return 0;
/* If shared icon, check whether it was already loaded */
if ( (loadflags & LR_SHARED)
&& (hIcon = CURSORICON_FindSharedIcon( hInstance, hRsrc ) ) != 0 )
return hIcon;
if (loadflags & LR_SHARED)
{
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;
bits = LockResource( handle );
@ -1325,15 +1266,9 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
hotspot.y = pt[1];
bits += 2 * sizeof(SHORT);
}
hIcon = CURSORICON_CreateIconFromBMI( (BITMAPINFO *)bits, hInstance, name, hotspot,
!fCursor, width, height, loadflags );
hIcon = CURSORICON_CreateIconFromBMI( (BITMAPINFO *)bits, hInstance, name, hRsrc,
hotspot, !fCursor, width, height, loadflags );
FreeResource( handle );
/* If shared icon, add to icon cache */
if ( hIcon && (loadflags & LR_SHARED) )
CURSORICON_AddSharedIcon( hInstance, hRsrc, hGroupRsrc, hIcon );
return hIcon;
}
@ -1447,7 +1382,7 @@ BOOL WINAPI DestroyIcon( HICON 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;
}
@ -2591,7 +2526,7 @@ HANDLE WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
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,
type == IMAGE_CURSOR, flags );
else