[3/10] user: Use 32-bit cursor handles
H. Verbeet
hverbeet at gmail.com
Sat Aug 5 16:39:10 CDT 2006
This patch makes user store the contents of a cursor / icon in the
server. A 16-bit handle is only created when required. Unfortunately
that still quite a few places due to 32->16 calls.
-------------- next part --------------
diff --git a/dlls/user/cursoricon.c b/dlls/user/cursoricon.c
index c644bc4..d58dedc 100644
--- a/dlls/user/cursoricon.c
+++ b/dlls/user/cursoricon.c
@@ -5,6 +5,7 @@
* 1996 Martin Von Loewis
* 1997 Alex Korobka
* 1998 Turchanov Sergey
+ * 2006 Henri Verbeet
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,7 +27,9 @@
*
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_icons.asp
*
- * Cursors and icons are stored in a global heap block, with the
+ * 32-bit cursors and icons are stored in the server.
+ *
+ * 16-bit cursors and icons are stored in a global heap block, with the
* following layout:
*
* CURSORICONINFO info;
@@ -50,6 +53,8 @@ #include <stdarg.h>
#include <string.h>
#include <stdlib.h>
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
@@ -206,7 +211,8 @@ static cursor_map_entry_t *remove_cursor
return entry;
}
-static HCURSOR create_cursor( unsigned int num_frames, unsigned int delay, HCURSOR16 cursor16 )
+/* Ask the server for a cursor */
+static HCURSOR create_cursor( unsigned int num_frames, unsigned int delay )
{
HCURSOR cursor = 0;
@@ -218,19 +224,10 @@ static HCURSOR create_cursor( unsigned i
}
SERVER_END_REQ;
- if (cursor)
- {
- cursor_map_entry_t *entry = HeapAlloc( GetProcessHeap(), 0, sizeof(cursor_map_entry_t) );
- entry->cursor16 = cursor16;
- entry->cursor32 = cursor;
-
- add_cursor16to32_entry( entry );
- add_cursor32to16_entry( entry );
- }
-
return cursor;
}
+/* Tell the server to kill a cursor */
static HCURSOR16 destroy_cursor( HCURSOR cursor )
{
cursor_map_entry_t *entry;
@@ -256,7 +253,73 @@ static HCURSOR16 destroy_cursor( HCURSOR
return GlobalFree16( cursor16 );
}
-HCURSOR16 get_cursor_handle16( HCURSOR cursor32 )
+/* Upload a cursor frame to the server */
+static void set_cursor_frame( HCURSOR cursor, unsigned int frame_idx, cursor_frame_t *frame )
+{
+ SERVER_START_REQ(set_cursor_frame)
+ {
+ req->handle = cursor;
+ req->frame_idx = frame_idx;
+ req->xhot = frame->xhot;
+ req->yhot = frame->yhot;
+ req->width = frame->width;
+ req->height = frame->height;
+ req->and_width_bytes = frame->and_width_bytes;
+ req->xor_width_bytes = frame->xor_width_bytes;
+ req->planes = frame->planes;
+ req->bpp = frame->bpp;
+ wine_server_add_data( req, frame->bits, (frame->and_width_bytes + frame->xor_width_bytes) * frame->height );
+ wine_server_call( req );
+ }
+ SERVER_END_REQ;
+}
+
+/* Download a cursor frame from the server */
+static BOOL get_cursor_frame( HCURSOR cursor, unsigned int frame_idx, cursor_frame_t *frame )
+{
+ NTSTATUS res;
+ /* Enough for a 32-bits 32x32 cursor / icon. */
+ unsigned int buffer_size = 4224;
+ unsigned int count = 0;
+
+ do
+ {
+ frame->bits = HeapAlloc(GetProcessHeap(), 0, buffer_size);
+ SERVER_START_REQ(get_cursor_frame)
+ {
+ req->handle = cursor;
+ req->frame_idx = frame_idx;
+ wine_server_set_reply( req, frame->bits, buffer_size);
+ if (!(res = wine_server_call_err( req )))
+ {
+ frame->xhot = reply->xhot;
+ frame->yhot = reply->yhot;
+ frame->width = reply->width;
+ frame->height = reply->height;
+ frame->and_width_bytes = reply->and_width_bytes;
+ frame->xor_width_bytes = reply->xor_width_bytes;
+ frame->planes = reply->planes;
+ frame->bpp = reply->bpp;
+ } else {
+ HeapFree( GetProcessHeap(), 0, frame->bits );
+ buffer_size = (reply->and_width_bytes + reply->xor_width_bytes) * reply->height;
+ }
+ }
+ SERVER_END_REQ;
+ } while (res == STATUS_BUFFER_OVERFLOW && !count++);
+
+ if (!frame->height)
+ {
+ HeapFree( GetProcessHeap(), 0, frame->bits );
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Lookup the cursor's 16-bit handle. Create one if it doesn't already exist. */
+HCURSOR16 get_cursor_handle16( HCURSOR cursor32, BOOL create )
{
cursor_map_entry_t *entry;
int idx = hash_cursor_handle( (DWORD)cursor32 );
@@ -269,6 +332,43 @@ HCURSOR16 get_cursor_handle16( HCURSOR c
if (entry->cursor32 == cursor32) return entry->cursor16;
}
+ /* 16-bit cursor handle not found, create one */
+ if (create)
+ {
+ size_t bits_size;
+ HCURSOR16 cursor16;
+ cursor_frame_t frame;
+
+ if (!get_cursor_frame( cursor32, 0, &frame )) return 0;
+
+ entry = HeapAlloc( GetProcessHeap(), 0, sizeof(cursor_map_entry_t) );
+ bits_size = (frame.and_width_bytes + frame.xor_width_bytes) * frame.height;
+ cursor16 = GlobalAlloc16( GMEM_MOVEABLE, sizeof(CURSORICONINFO) + bits_size );
+ if (cursor16)
+ {
+ CURSORICONINFO *info;
+
+ info = (CURSORICONINFO *)GlobalLock16( cursor16 );
+ info->ptHotSpot.x = frame.xhot;
+ info->ptHotSpot.y = frame.yhot;
+ info->nWidth = frame.width;
+ info->nHeight = frame.height;
+ info->nWidthBytes = frame.xor_width_bytes;
+ info->bPlanes = frame.planes;
+ info->bBitsPerPixel = frame.bpp;
+ CopyMemory( info + 1, frame.bits, bits_size );
+ GlobalUnlock16( cursor16 );
+ }
+ HeapFree( GetProcessHeap(), 0, frame.bits );
+
+ entry->cursor16 = cursor16;
+ entry->cursor32 = cursor32;
+ add_cursor16to32_entry( entry );
+ add_cursor32to16_entry( entry );
+
+ return cursor16;
+ }
+
return 0;
}
@@ -832,7 +932,8 @@ HICON WINAPI CreateIconFromResourceEx( L
INT width, INT height,
UINT cFlag )
{
- HGLOBAL16 hObj;
+ HCURSOR cursor;
+ cursor_frame_t frame = {0};
static HDC hdcMem;
int sizeAnd, sizeXor;
HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */
@@ -998,38 +1099,31 @@ HICON WINAPI CreateIconFromResourceEx( L
return 0;
}
- /* Now create the CURSORICONINFO structure */
+ /* Setup a cursor frame, send it to the server */
GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
- hObj = GlobalAlloc16( GMEM_MOVEABLE,
- sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
- if (hObj)
- {
- CURSORICONINFO *info;
-
- info = (CURSORICONINFO *)GlobalLock16( hObj );
- info->ptHotSpot.x = hotspot.x;
- info->ptHotSpot.y = hotspot.y;
- info->nWidth = bmpXor.bmWidth;
- info->nHeight = bmpXor.bmHeight;
- info->nWidthBytes = bmpXor.bmWidthBytes;
- info->bPlanes = bmpXor.bmPlanes;
- info->bBitsPerPixel = bmpXor.bmBitsPixel;
-
- /* Transfer the bitmap bits to the CURSORICONINFO structure */
-
- GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
- GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
- GlobalUnlock16( hObj );
- }
+ cursor = create_cursor( 1, 0 );
+ frame.xhot = hotspot.x;
+ frame.yhot = hotspot.y;
+ frame.width = bmpXor.bmWidth;
+ frame.height = bmpXor.bmHeight;
+ frame.and_width_bytes = bmpAnd.bmWidthBytes;
+ frame.xor_width_bytes = bmpXor.bmWidthBytes;
+ frame.planes = bmpXor.bmPlanes;
+ frame.bpp = bmpXor.bmBitsPixel;
+ frame.bits = HeapAlloc( GetProcessHeap(), 0, sizeAnd + sizeXor );
+ GetBitmapBits( hAndBits, sizeAnd, frame.bits );
+ GetBitmapBits( hXorBits, sizeXor, frame.bits + sizeAnd );
+ set_cursor_frame( cursor, 0, &frame );
+ HeapFree( GetProcessHeap(), 0, frame.bits );
DeleteObject( hAndBits );
DeleteObject( hXorBits );
- return create_cursor( 1, 0, hObj );
+ return cursor;
}
@@ -1167,22 +1261,20 @@ static HICON CURSORICON_Load(HINSTANCE h
*/
static HICON CURSORICON_Copy( HINSTANCE16 hInst16, HICON hIcon )
{
- char *ptrOld, *ptrNew;
- int size;
- HICON16 hOld = HICON_16(hIcon);
- HICON16 hNew;
+ /* Should animated cursors be copyable like this as well? */
+ HCURSOR new_cursor;
+ cursor_frame_t frame;
- if (!(ptrOld = (char *)GlobalLock16( hOld ))) return 0;
- if (hInst16 && !(hInst16 = GetExePtr( hInst16 ))) return 0;
- size = GlobalSize16( hOld );
- hNew = GlobalAlloc16( GMEM_MOVEABLE, size );
- FarSetOwner16( hNew, hInst16 );
- ptrNew = (char *)GlobalLock16( hNew );
- memcpy( ptrNew, ptrOld, size );
- GlobalUnlock16( hOld );
- GlobalUnlock16( hNew );
+ if (!hIcon || !get_cursor_frame( hIcon, 0, &frame ))
+ {
+ return 0;
+ }
+
+ new_cursor = create_cursor( 1, 0 );
+ set_cursor_frame( new_cursor, 0, &frame );
+ HeapFree( GetProcessHeap(), 0, frame.bits );
- return create_cursor( 1, 0, hNew );
+ return new_cursor;
}
/*************************************************************************
@@ -1485,25 +1577,31 @@ HGLOBAL16 WINAPI CreateCursorIconIndirec
LPCVOID lpANDbits,
LPCVOID lpXORbits )
{
- HGLOBAL16 handle;
- char *ptr;
+ HCURSOR cursor;
+ cursor_frame_t frame;
int sizeAnd, sizeXor;
- hInstance = GetExePtr( hInstance ); /* Make it a module handle */
if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
info->nWidthBytes = get_bitmap_width_bytes(info->nWidth,info->bBitsPerPixel);
sizeXor = info->nHeight * info->nWidthBytes;
sizeAnd = info->nHeight * get_bitmap_width_bytes( info->nWidth, 1 );
- if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
- sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
- return 0;
- FarSetOwner16( handle, hInstance );
- ptr = (char *)GlobalLock16( handle );
- memcpy( ptr, info, sizeof(*info) );
- memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd );
- memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor );
- GlobalUnlock16( handle );
- return HICON_16(create_cursor( 1, 0, handle ));
+
+ cursor = create_cursor( 1, 0 );
+ frame.xhot = info->ptHotSpot.x;
+ frame.yhot = info->ptHotSpot.y;
+ frame.width = info->nWidth;
+ frame.height = info->nHeight;
+ frame.and_width_bytes = get_bitmap_width_bytes( info->nWidth, 1 );
+ frame.xor_width_bytes = info->nWidthBytes;
+ frame.planes = info->bPlanes;
+ frame.bpp = info->bBitsPerPixel;
+ frame.bits = HeapAlloc( GetProcessHeap(), 0, sizeAnd + sizeXor );
+ CopyMemory( frame.bits, lpANDbits, sizeAnd );
+ CopyMemory( frame.bits + sizeAnd, lpXORbits, sizeXor );
+ set_cursor_frame( cursor, 0, &frame );
+ HeapFree( GetProcessHeap(), 0, frame.bits );
+
+ return HICON_16(cursor);
}
@@ -1966,8 +2064,9 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PIC
*/
HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
{
+ HCURSOR cursor;
+ cursor_frame_t frame;
BITMAP bmpXor,bmpAnd;
- HICON16 hObj;
int sizeXor,sizeAnd;
if (iconinfo->hbmColor) GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
@@ -1976,51 +2075,46 @@ HICON WINAPI CreateIconIndirect(PICONINF
sizeXor = iconinfo->hbmColor ? (bmpXor.bmHeight * bmpXor.bmWidthBytes) : 0;
sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
- hObj = GlobalAlloc16( GMEM_MOVEABLE,
- sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
- if (hObj)
- {
- CURSORICONINFO *info;
-
- info = (CURSORICONINFO *)GlobalLock16( hObj );
-
- /* If we are creating an icon, the hotspot is unused */
- if (iconinfo->fIcon)
- {
- info->ptHotSpot.x = ICON_HOTSPOT;
- info->ptHotSpot.y = ICON_HOTSPOT;
- }
- else
- {
- info->ptHotSpot.x = iconinfo->xHotspot;
- info->ptHotSpot.y = iconinfo->yHotspot;
- }
-
- if (iconinfo->hbmColor)
- {
- info->nWidth = bmpXor.bmWidth;
- info->nHeight = bmpXor.bmHeight;
- info->nWidthBytes = bmpXor.bmWidthBytes;
- info->bPlanes = bmpXor.bmPlanes;
- info->bBitsPerPixel = bmpXor.bmBitsPixel;
- }
- else
- {
- info->nWidth = bmpAnd.bmWidth;
- info->nHeight = bmpAnd.bmHeight / 2;
- info->nWidthBytes = bmpAnd.bmWidthBytes;
- info->bPlanes = bmpAnd.bmPlanes;
- info->bBitsPerPixel = bmpAnd.bmBitsPixel;
- }
+ cursor = create_cursor( 1, 0 );
- /* Transfer the bitmap bits to the CURSORICONINFO structure */
+ /* If we are creating an icon, the hotspot is unused */
+ if (iconinfo->fIcon)
+ {
+ frame.xhot = ICON_HOTSPOT;
+ frame.yhot = ICON_HOTSPOT;
+ }
+ else
+ {
+ frame.xhot = iconinfo->xHotspot;
+ frame.yhot = iconinfo->yHotspot;
+ }
- GetBitmapBits( iconinfo->hbmMask, sizeAnd, (char*)(info + 1) );
- if (iconinfo->hbmColor) GetBitmapBits( iconinfo->hbmColor, sizeXor, (char*)(info + 1) + sizeAnd );
- GlobalUnlock16( hObj );
+ if (iconinfo->hbmColor)
+ {
+ frame.width = bmpXor.bmWidth;
+ frame.height = bmpXor.bmHeight;
+ frame.and_width_bytes = bmpAnd.bmWidthBytes;
+ frame.xor_width_bytes = bmpXor.bmWidthBytes;
+ frame.planes = bmpXor.bmPlanes;
+ frame.bpp = bmpXor.bmBitsPixel;
+ }
+ else
+ {
+ frame.width = bmpAnd.bmWidth;
+ frame.height = bmpAnd.bmHeight / 2;
+ frame.and_width_bytes = bmpAnd.bmWidthBytes;
+ frame.xor_width_bytes = 0;
+ frame.planes = bmpAnd.bmPlanes;
+ frame.bpp = bmpAnd.bmBitsPixel;
}
- return create_cursor( 1, 0, hObj );
+ frame.bits = HeapAlloc( GetProcessHeap(), 0, sizeAnd + sizeXor );
+ GetBitmapBits( iconinfo->hbmMask, sizeAnd, frame.bits );
+ if (iconinfo->hbmColor) GetBitmapBits( iconinfo->hbmColor, sizeXor, frame.bits + sizeAnd );
+ set_cursor_frame( cursor, 0, &frame );
+ HeapFree( GetProcessHeap(), 0, frame.bits );
+
+ return cursor;
}
/******************************************************************************
diff --git a/dlls/user/user_private.h b/dlls/user/user_private.h
index 9bd1d38..f41e37a 100644
--- a/dlls/user/user_private.h
+++ b/dlls/user/user_private.h
@@ -232,11 +232,11 @@ extern void SPY_ExitMessage( INT iFlag,
extern int SPY_Init(void);
/* HANDLE16 <-> HANDLE conversions */
-HCURSOR16 get_cursor_handle16( HCURSOR cursor32 );
+HCURSOR16 get_cursor_handle16( HCURSOR cursor32, BOOL create );
HCURSOR get_cursor_handle32( HCURSOR16 cursor16 );
-#define HCURSOR_16(h32) get_cursor_handle16(h32)
-#define HICON_16(h32) get_cursor_handle16(h32)
+#define HCURSOR_16(h32) get_cursor_handle16(h32, TRUE)
+#define HICON_16(h32) get_cursor_handle16(h32, TRUE)
#define HINSTANCE_16(h32) (LOWORD(h32))
#define HCURSOR_32(h16) get_cursor_handle32(h16)
diff --git a/include/wine/winuser16.h b/include/wine/winuser16.h
index 8ed9965..e795e7c 100644
--- a/include/wine/winuser16.h
+++ b/include/wine/winuser16.h
@@ -148,6 +148,25 @@ typedef struct
/* Cursors / Icons */
+typedef struct {
+ unsigned short xhot;
+ unsigned short yhot;
+ unsigned short width;
+ unsigned short height;
+ unsigned short and_width_bytes;
+ unsigned short xor_width_bytes;
+ unsigned char planes;
+ unsigned char bpp;
+ /* XOR & AND bitmap bits */
+ unsigned char *bits;
+} cursor_frame_t;
+
+typedef struct cursor_t {
+ unsigned int num_frames;
+ unsigned short delay;
+ cursor_frame_t *frames;
+} cursor_t;
+
typedef struct tagCURSORICONINFO
{
POINT16 ptHotSpot;
More information about the wine-patches
mailing list