From b6b2e4543ee90fc21867ad3a89ab8c83c518b114 Mon Sep 17 00:00:00 2001 From: Erich Hoover Date: Sat, 8 May 2010 16:07:25 -0600 Subject: user32/winex11: Add support for multiple frames in cursor format. --- dlls/user32/cursoricon.c | 102 +++++++++++++++++++++++++++----------------- dlls/user32/driver.c | 6 +- dlls/user32/user_private.h | 2 +- dlls/winex11.drv/mouse.c | 69 +++++++++++++++++++----------- 4 files changed, 111 insertions(+), 68 deletions(-) diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index bdaf187..57d4485 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -112,26 +112,35 @@ static const WORD ICON_HOTSPOT = 0x4242; /********************************************************************** * User objects management */ +typedef struct { + DWORD nFrames; /* Total number of stored frames */ + DWORD nMsDelay; /* Millsecond delay between frames */ + ICONINFO frames[]; /* Array of 32-bit cursors or a single-element icon */ +} WINECURSORICON; struct cursoricon_object { struct user_object obj; /* object header */ ULONG_PTR param; /* opaque param used by 16-bit code */ - ICONINFO icon; /* 32-bit cursor or icon */ + WINECURSORICON icon; /* Internal 32-bit cursor/icon information */ }; -static HICON alloc_icon_handle( ICONINFO iconinfo ) +static HICON alloc_icon_handle( ICONINFO *iconinfo, DWORD nFrames, DWORD nMsDelay ) { - int alloc_size = sizeof(struct cursoricon_object); + int alloc_size = sizeof(struct cursoricon_object) + nFrames*(sizeof(ICONINFO)); struct cursoricon_object *obj = HeapAlloc( GetProcessHeap(), 0, alloc_size ); + int i; if (!obj) return 0; obj->param = 0; - obj->icon = iconinfo; + obj->icon.nFrames = nFrames; + obj->icon.nMsDelay = nMsDelay; + for (i=0; iicon.frames[i], &iconinfo[i], sizeof(ICONINFO)); return alloc_user_handle( &obj->obj, USER_ICON ); } -static ICONINFO *get_icon_ptr( HICON handle ) +static WINECURSORICON *get_icon_ptr( HICON handle ) { struct cursoricon_object *obj = get_user_handle_ptr( handle, USER_ICON ); if (obj == OBJ_OTHER_PROCESS) @@ -142,9 +151,9 @@ static ICONINFO *get_icon_ptr( HICON handle ) return obj ? &(obj->icon) : NULL; } -static void release_icon_ptr( HICON handle, ICONINFO *ptr ) +static void release_icon_ptr( HICON handle, WINECURSORICON *ptr ) { - release_user_handle_ptr( (char*)ptr + sizeof(ICONINFO) - sizeof(struct cursoricon_object) ); + release_user_handle_ptr( (char*)ptr + sizeof(WINECURSORICON) - sizeof(struct cursoricon_object) ); } static BOOL free_icon_handle( HICON handle ) @@ -155,10 +164,15 @@ static BOOL free_icon_handle( HICON handle ) else if (obj) { ULONG_PTR param = obj->param; + int i; + HeapFree( GetProcessHeap(), 0, obj ); if (wow_handlers.free_icon_param && param) wow_handlers.free_icon_param( param ); - DeleteObject( obj->icon.hbmMask ); - DeleteObject( obj->icon.hbmColor ); + for (i=0; iicon.nFrames; i++) + { + DeleteObject( obj->icon.frames[i].hbmMask ); + DeleteObject( obj->icon.frames[i].hbmColor ); + } USER_Driver->pDestroyCursorIcon( handle ); return TRUE; } @@ -499,11 +513,11 @@ static INT CURSORICON_DelSharedIcon( HICON hIcon ) */ BOOL get_icon_size( HICON handle, SIZE *size ) { - ICONINFO *icon; + WINECURSORICON *icon; BITMAP bmpAnd; if (!(icon = get_icon_ptr( handle ))) return FALSE; - GetObjectW( icon->hbmMask, sizeof(bmpAnd), &bmpAnd ); + GetObjectW( icon->frames[0].hbmMask, sizeof(bmpAnd), &bmpAnd ); size->cx = bmpAnd.bmWidth; size->cy = bmpAnd.bmHeight; release_icon_ptr( handle, icon ); @@ -908,14 +922,14 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, iconinfo.yHotspot = hotspot.y; iconinfo.hbmMask = hAndBits; iconinfo.hbmColor = hXorBits; - hObj = alloc_icon_handle( iconinfo ); + hObj = alloc_icon_handle( &iconinfo, 1, 0 ); if (!hObj) { DeleteObject( hAndBits ); DeleteObject( hXorBits ); } else - USER_Driver->pCreateCursorIcon( hObj, &iconinfo ); + USER_Driver->pCreateCursorIcon( hObj, &iconinfo, 1, 0 ); return hObj; } @@ -1648,18 +1662,27 @@ static BOOL CURSORICON_CloneBitmaps( ICONINFO *src, ICONINFO *dst, BOOL convert_ */ HICON WINAPI CopyIcon( HICON hIcon ) { - ICONINFO *ptrOld; - ICONINFO newIcon; - HICON hNew; + WINECURSORICON *ptrOld; + ICONINFO *newIcon; + HICON hNew = NULL; + INT size, i; if (!(ptrOld = get_icon_ptr( hIcon ))) return 0; - memset(&newIcon, 0, sizeof(ICONINFO)); - if (!CURSORICON_CloneBitmaps( ptrOld, &newIcon, FALSE )) - return NULL; - hNew = alloc_icon_handle( newIcon ); - release_icon_ptr( hIcon, ptrOld ); - USER_Driver->pCreateCursorIcon( hNew, &newIcon ); - return hNew; + size = sizeof(ICONINFO)*ptrOld->nFrames; + newIcon = (ICONINFO *) HeapAlloc(GetProcessHeap(), 0, size); + if (!newIcon) return 0; + memset(newIcon, 0, size); + for (i=0; inFrames; i++) + { + if (!CURSORICON_CloneBitmaps( &ptrOld->frames[i], &newIcon[i], FALSE )) + goto cleanup; + } + hNew = alloc_icon_handle( newIcon, ptrOld->nFrames, ptrOld->nMsDelay ); + USER_Driver->pCreateCursorIcon( hNew, newIcon, 1, 0 ); + +cleanup: + HeapFree(GetProcessHeap(), 0, newIcon); + return hNew; } @@ -1998,18 +2021,18 @@ HICON WINAPI LoadIconA(HINSTANCE hInstance, LPCSTR name) */ BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo) { + WINECURSORICON *icon; BOOL ret = FALSE; - ICONINFO *icon; if (!(icon = get_icon_ptr( hIcon ))) return FALSE; - *iconinfo = *icon; - if ( (icon->xHotspot == ICON_HOTSPOT) && - (icon->yHotspot == ICON_HOTSPOT) ) + *iconinfo = icon->frames[0]; + if ( (icon->frames[0].xHotspot == ICON_HOTSPOT) && + (icon->frames[0].yHotspot == ICON_HOTSPOT) ) { BITMAP bmpAnd; - GetObjectW( icon->hbmMask, sizeof(bmpAnd), &bmpAnd ); + GetObjectW( icon->frames[0].hbmMask, sizeof(bmpAnd), &bmpAnd ); iconinfo->fIcon = TRUE; iconinfo->xHotspot = bmpAnd.bmWidth / 2; iconinfo->yHotspot = bmpAnd.bmWidth / 2; /* bmWidth use intentional */ @@ -2017,10 +2040,10 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo) else { iconinfo->fIcon = FALSE; - iconinfo->xHotspot = icon->xHotspot; - iconinfo->yHotspot = icon->yHotspot; + iconinfo->xHotspot = icon->frames[0].xHotspot; + iconinfo->yHotspot = icon->frames[0].yHotspot; } - if (CURSORICON_CloneBitmaps( icon, iconinfo, TRUE )) + if (CURSORICON_CloneBitmaps( &icon->frames[0], iconinfo, TRUE )) ret = TRUE; release_icon_ptr( hIcon, icon ); @@ -2067,10 +2090,11 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) iinfo.xHotspot = iconinfo->xHotspot; iinfo.yHotspot = iconinfo->yHotspot; } - if (CURSORICON_CloneBitmaps( iconinfo, &iinfo, FALSE )) + + if (CURSORICON_CloneBitmaps( &iconinfo[0], &iinfo, FALSE )) { - hObj = alloc_icon_handle( iinfo ); - USER_Driver->pCreateCursorIcon( hObj, &iinfo ); + hObj = alloc_icon_handle( &iinfo, 1, 0 ); + USER_Driver->pCreateCursorIcon( hObj, &iinfo, 1, 0 ); } return hObj; } @@ -2100,7 +2124,7 @@ BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon, INT cxWidth, INT cyWidth, UINT istep, HBRUSH hbr, UINT flags ) { - ICONINFO *icon; + WINECURSORICON *icon; HDC hDC_off = 0, hMemDC; BOOL result = FALSE, DoOffscreen; HBITMAP hB_off = 0, hOld = 0; @@ -2125,8 +2149,8 @@ BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon, if (flags & DI_NOMIRROR) FIXME_(icon)("Ignoring flag DI_NOMIRROR\n"); - GetObjectW( icon->hbmMask, sizeof(bmpAnd), &bmpAnd ); - GetObjectW( icon->hbmColor, sizeof(bmpXor), &bmpXor ); + GetObjectW( icon->frames[istep].hbmMask, sizeof(bmpAnd), &bmpAnd ); + GetObjectW( icon->frames[istep].hbmColor, sizeof(bmpXor), &bmpXor ); andLength = bmpAnd.bmHeight * get_bitmap_width_bytes( bmpAnd.bmWidth, bmpAnd.bmBitsPixel); @@ -2135,8 +2159,8 @@ BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon, andBitmapBits = (unsigned char *) HeapAlloc(GetProcessHeap(), 0, andLength); xorBitmapBits = (unsigned char *) HeapAlloc(GetProcessHeap(), 0, dibLength); - GetBitmapBits( icon->hbmMask, andLength, andBitmapBits ); - CURSORICON_GetXorBits( icon, (char *)xorBitmapBits ); + GetBitmapBits( icon->frames[istep].hbmMask, andLength, andBitmapBits ); + CURSORICON_GetXorBits( &icon->frames[istep], (char *)xorBitmapBits ); if (flags & DI_IMAGE) has_alpha = bitmap_has_alpha_channel( diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index aa6f032..87a95f2 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -217,7 +217,7 @@ static SHORT CDECL nulldrv_VkKeyScanEx( WCHAR ch, HKL layout ) return -1; } -static void CDECL nulldrv_CreateCursorIcon( HCURSOR cursor, struct _ICONINFO *info ) +static void CDECL nulldrv_CreateCursorIcon( HCURSOR cursor, struct _ICONINFO *info, DWORD nFrames, DWORD nMsDelay ) { } @@ -570,9 +570,9 @@ static SHORT CDECL loaderdrv_VkKeyScanEx( WCHAR ch, HKL layout ) return load_driver()->pVkKeyScanEx( ch, layout ); } -static void CDECL loaderdrv_CreateCursorIcon( HCURSOR cursor, struct _ICONINFO *info ) +static void CDECL loaderdrv_CreateCursorIcon( HCURSOR cursor, struct _ICONINFO *info, DWORD nFrames, DWORD nMsDelay ) { - load_driver()->pCreateCursorIcon( cursor, info ); + load_driver()->pCreateCursorIcon( cursor, info, nFrames, nMsDelay ); } static void CDECL loaderdrv_DestroyCursorIcon( HCURSOR cursor ) diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 3ef7435..22a77fd 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -68,7 +68,7 @@ typedef struct tagUSER_DRIVER { BOOL (CDECL *pUnloadKeyboardLayout)(HKL); SHORT (CDECL *pVkKeyScanEx)(WCHAR, HKL); /* cursor/icon functions */ - void (CDECL *pCreateCursorIcon)(HCURSOR,struct _ICONINFO *); + void (CDECL *pCreateCursorIcon)(HCURSOR,struct _ICONINFO *,DWORD,DWORD); void (CDECL *pDestroyCursorIcon)(HCURSOR); void (CDECL *pSetCursor)(HCURSOR); BOOL (CDECL *pGetCursorPos)(LPPOINT); diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index e534abb..c984aec 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -32,6 +32,9 @@ static void *xcursor_handle; MAKE_FUNCPTR(XcursorImageCreate); MAKE_FUNCPTR(XcursorImageDestroy); MAKE_FUNCPTR(XcursorImageLoadCursor); +MAKE_FUNCPTR(XcursorImagesCreate); +MAKE_FUNCPTR(XcursorImagesDestroy); +MAKE_FUNCPTR(XcursorImagesLoadCursor); # undef MAKE_FUNCPTR #endif /* SONAME_LIBXCURSOR */ @@ -114,6 +117,9 @@ void X11DRV_Xcursor_Init(void) LOAD_FUNCPTR(XcursorImageCreate); LOAD_FUNCPTR(XcursorImageDestroy); LOAD_FUNCPTR(XcursorImageLoadCursor); + LOAD_FUNCPTR(XcursorImagesCreate); + LOAD_FUNCPTR(XcursorImagesDestroy); + LOAD_FUNCPTR(XcursorImagesLoadCursor); #undef LOAD_FUNCPTR #endif /* SONAME_LIBXCURSOR */ } @@ -657,29 +663,42 @@ cleanup: * * Use Xcursor to create an X cursor from a Windows one. */ -static Cursor create_xcursor_cursor( Display *display, ICONINFO *icon ) +static Cursor create_xcursor_cursor( Display *display, ICONINFO *icon, DWORD nFrames, DWORD nMsDelay ) { - Cursor cursor; + int i, succeeded = FALSE; + XcursorImages *images; XcursorImage *image; + Cursor cursor; - image = create_cursor_image( icon ); - if (!image) return 0; + images = pXcursorImagesCreate( nFrames ); + if (!images) return 0; - /* Make sure hotspot is valid */ - image->xhot = icon->xHotspot; - image->yhot = icon->yHotspot; - if (image->xhot >= image->width || - image->yhot >= image->height) + for (i = 0; i < nFrames; i++) { - image->xhot = image->width / 2; - image->yhot = image->height / 2; - } + ICONINFO *frame = &icon[i]; + + image = create_cursor_image( frame ); + if (!image) goto cleanup; + + /* Make sure hotspot is valid */ + image->xhot = frame->xHotspot; + image->yhot = frame->yHotspot; + if (image->xhot >= image->width || + image->yhot >= image->height) + { + image->xhot = image->width / 2; + image->yhot = image->height / 2; + } - image->delay = 0; + image->delay = nMsDelay; + images->images[images->nimage++] = image; + } - cursor = pXcursorImageLoadCursor( display, image ); - pXcursorImageDestroy( image ); + succeeded = TRUE; + cursor = pXcursorImagesLoadCursor( display, images ); +cleanup: + pXcursorImagesDestroy( images ); return cursor; } @@ -691,7 +710,7 @@ static Cursor create_xcursor_cursor( Display *display, ICONINFO *icon ) * * Create an X cursor from a Windows one. */ -static Cursor create_cursor( Display *display, ICONINFO *icon ) +static Cursor create_cursor( Display *display, ICONINFO *icon, DWORD nFrames, DWORD nMsDelay ) { char *and_bits = NULL, *xor_bits = NULL; Pixmap pixmapBits, pixmapMask, pixmapMaskInv = 0, pixmapAll; @@ -704,7 +723,7 @@ static Cursor create_cursor( Display *display, ICONINFO *icon ) if (!icon) return get_empty_cursor(); #ifdef SONAME_LIBXCURSOR - if (pXcursorImageLoadCursor) return create_xcursor_cursor( display, icon ); + if (pXcursorImageLoadCursor) return create_xcursor_cursor( display, icon, nFrames, nMsDelay ); #endif /* Create the X cursor from the bits */ @@ -714,8 +733,8 @@ static Cursor create_cursor( Display *display, ICONINFO *icon ) XImage *image; GC gc; - GetObjectW( icon->hbmMask, sizeof(bmpAnd), &bmpAnd ); - GetObjectW( icon->hbmColor, sizeof(bmpXor), &bmpXor ); + GetObjectW( icon[0].hbmMask, sizeof(bmpAnd), &bmpAnd ); + GetObjectW( icon[0].hbmColor, sizeof(bmpXor), &bmpXor ); TRACE("Bitmap %dx%d planes=%d bpp=%d bytesperline=%d\n", bmpAnd.bmWidth, bmpAnd.bmHeight, bmpXor.bmPlanes, bmpXor.bmBitsPixel, @@ -726,8 +745,8 @@ static Cursor create_cursor( Display *display, ICONINFO *icon ) and_bits = (char *) HeapAlloc(GetProcessHeap(), 0, dibLength); xor_bits = (char *) HeapAlloc(GetProcessHeap(), 0, xorLength); - GetBitmapBits( icon->hbmMask, dibLength, and_bits ); - GetBitmapBits( icon->hbmColor, xorLength, xor_bits ); + GetBitmapBits( icon[0].hbmMask, dibLength, and_bits ); + GetBitmapBits( icon[0].hbmColor, xorLength, xor_bits ); /* Create a pixmap and transfer all the bits to it */ @@ -987,8 +1006,8 @@ static Cursor create_cursor( Display *display, ICONINFO *icon ) } /* Make sure hotspot is valid */ - hotspot.x = icon->xHotspot; - hotspot.y = icon->yHotspot; + hotspot.x = icon[0].xHotspot; + hotspot.y = icon[0].yHotspot; if (hotspot.x < 0 || hotspot.x >= bmpAnd.bmWidth || hotspot.y < 0 || hotspot.y >= bmpAnd.bmHeight) { @@ -1018,7 +1037,7 @@ cleanup: /*********************************************************************** * CreateCursorIcon (X11DRV.@) */ -void CDECL X11DRV_CreateCursorIcon( HCURSOR handle, ICONINFO *icon ) +void CDECL X11DRV_CreateCursorIcon( HCURSOR handle, ICONINFO *icon, DWORD nFrames, DWORD nMsDelay ) { static const WORD ICON_HOTSPOT = 0x4242; Cursor cursor; @@ -1027,7 +1046,7 @@ void CDECL X11DRV_CreateCursorIcon( HCURSOR handle, ICONINFO *icon ) if (icon->xHotspot == ICON_HOTSPOT && icon->yHotspot == ICON_HOTSPOT) return; wine_tsx11_lock(); - cursor = create_cursor( gdi_display, icon ); + cursor = create_cursor( gdi_display, icon, nFrames, nMsDelay ); if (cursor) { if (!cursor_context) cursor_context = XUniqueContext(); -- 1.7.0.4