From 6f481467d59cea3a6842bdf96c2a61e580384d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Sat, 10 Nov 2012 15:56:42 +0000 Subject: [PATCH] [WIN32K] - Implement usage of alpha cursors (does not work yet due to a bug in windres) - Directly use bitmaps passed to NtUserSetCursorIconData instead of copying them svn path=/trunk/; revision=57695 --- reactos/win32ss/gdi/eng/mouse.c | 87 +++++++++++++------ reactos/win32ss/gdi/eng/mouse.h | 3 +- reactos/win32ss/gdi/eng/pdevobj.h | 1 + reactos/win32ss/user/ntuser/cursoricon_new.c | 80 ++++++----------- reactos/win32ss/user/ntuser/msgqueue.c | 30 ++++--- .../user/user32/windows/cursoricon_new.c | 66 ++++++++------ 6 files changed, 149 insertions(+), 118 deletions(-) diff --git a/reactos/win32ss/gdi/eng/mouse.c b/reactos/win32ss/gdi/eng/mouse.c index ecc18e2f110..0600f266fb7 100644 --- a/reactos/win32ss/gdi/eng/mouse.c +++ b/reactos/win32ss/gdi/eng/mouse.c @@ -232,29 +232,51 @@ IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest) /* Blt the pointer on the screen. */ if (pgp->psurfColor) { - IntEngBitBlt(psoDest, - &pgp->psurfMask->SurfObj, - NULL, - NULL, - NULL, - &rclSurf, - (POINTL*)&rclPointer, - NULL, - NULL, - NULL, - ROP4_FROM_INDEX(R3_OPINDEX_SRCAND)); + if(!(pgp->flags & SPS_ALPHA)) + { + IntEngBitBlt(psoDest, + &pgp->psurfMask->SurfObj, + NULL, + NULL, + NULL, + &rclSurf, + (POINTL*)&rclPointer, + NULL, + NULL, + NULL, + ROP4_SRCAND); - IntEngBitBlt(psoDest, - &pgp->psurfColor->SurfObj, - NULL, - NULL, - NULL, - &rclSurf, - (POINTL*)&rclPointer, - NULL, - NULL, - NULL, - ROP4_FROM_INDEX(R3_OPINDEX_SRCINVERT)); + IntEngBitBlt(psoDest, + &pgp->psurfColor->SurfObj, + NULL, + NULL, + NULL, + &rclSurf, + (POINTL*)&rclPointer, + NULL, + NULL, + NULL, + ROP4_SRCINVERT); + } + else + { + BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } }; + EXLATEOBJ exlo; + EXLATEOBJ_vInitialize(&exlo, + pgp->psurfColor->ppal, + ppdev->ppalSurf, + 0xFFFFFFFF, + 0xFFFFFFFF, + 0); + IntEngAlphaBlend(psoDest, + &pgp->psurfColor->SurfObj, + NULL, + &exlo.xlo, + &rclSurf, + &rclPointer, + &blendobj); + EXLATEOBJ_vCleanup(&exlo); + } } else { @@ -352,7 +374,15 @@ EngSetPointerShape( if (psoColor) { /* Color bitmap must have the same format as the dest surface */ - if (psoColor->iBitmapFormat != pso->iBitmapFormat) goto failure; + if (psoColor->iBitmapFormat != pso->iBitmapFormat) + { + /* It's OK if we have an alpha bitmap */ + if(!(fl & SPS_ALPHA)) + { + DPRINT1("Screen surface and cursor color bitmap format don't match!.\n"); + goto failure; + } + } /* Create a bitmap to copy the color bitmap to */ hbmColor = EngCreateBitmap(psoColor->sizlBitmap, @@ -452,6 +482,7 @@ EngSetPointerShape( pgp->HotSpot.x = xHot; pgp->HotSpot.y = yHot; pgp->Size = sizel; + pgp->flags = fl; if (x != -1) { @@ -598,12 +629,12 @@ GreSetPointerShape( LONG xHot, LONG yHot, LONG x, - LONG y) + LONG y, + FLONG fl) { PDC pdc; PSURFACE psurf, psurfMask, psurfColor; EXLATEOBJ exlo; - FLONG fl = 0; ULONG ulResult = 0; pdc = DC_LockDc(hdc); @@ -629,7 +660,10 @@ GreSetPointerShape( if (hbmMask) psurfMask = SURFACE_ShareLockSurface(hbmMask); else + { + ASSERT(fl & SPS_ALPHA); psurfMask = NULL; + } /* Check for color bitmap */ if (hbmColor) @@ -645,6 +679,9 @@ GreSetPointerShape( } else psurfColor = NULL; + + /* We must have a valid surface in case of alpha bitmap */ + ASSERT(((fl & SPS_ALPHA) && psurfColor) || !(fl & SPS_ALPHA)); /* Call the driver or eng function */ ulResult = IntEngSetPointerShape(&psurf->SurfObj, diff --git a/reactos/win32ss/gdi/eng/mouse.h b/reactos/win32ss/gdi/eng/mouse.h index 414f49c24c3..719be1e77bc 100644 --- a/reactos/win32ss/gdi/eng/mouse.h +++ b/reactos/win32ss/gdi/eng/mouse.h @@ -12,7 +12,8 @@ GreSetPointerShape( LONG xHot, LONG yHot, LONG x, - LONG y); + LONG y, + FLONG fl); VOID NTAPI diff --git a/reactos/win32ss/gdi/eng/pdevobj.h b/reactos/win32ss/gdi/eng/pdevobj.h index 77f315b65ab..4f3a6496858 100644 --- a/reactos/win32ss/gdi/eng/pdevobj.h +++ b/reactos/win32ss/gdi/eng/pdevobj.h @@ -34,6 +34,7 @@ typedef struct _GDIPOINTER /* should stay private to ENG? No, part of PDEVOBJ ak SURFACE *psurfColor; SURFACE *psurfMask; SURFACE *psurfSave; + FLONG flags; /* Public pointer information */ RECTL Exclude; /* Required publicly for SPS_ACCEPT_EXCLUDE */ diff --git a/reactos/win32ss/user/ntuser/cursoricon_new.c b/reactos/win32ss/user/ntuser/cursoricon_new.c index 8d0c0703192..c80df050dd8 100644 --- a/reactos/win32ss/user/ntuser/cursoricon_new.c +++ b/reactos/win32ss/user/ntuser/cursoricon_new.c @@ -923,7 +923,6 @@ NtUserSetCursorIconData( PCURICON_OBJECT CurIcon; NTSTATUS Status = STATUS_SUCCESS; BOOL Ret = FALSE; - CURSORDATA dataSafe; TRACE("Enter NtUserSetCursorIconData\n"); @@ -943,7 +942,15 @@ NtUserSetCursorIconData( _SEH2_TRY { ProbeForRead(pCursorData, sizeof(*pCursorData), 1); - RtlCopyMemory(&dataSafe, pCursorData, sizeof(dataSafe)); + CurIcon->xHotspot = pCursorData->xHotspot; + CurIcon->yHotspot = pCursorData->yHotspot; + CurIcon->cx = pCursorData->cx; + CurIcon->cy = pCursorData->cy; + CurIcon->rt = pCursorData->rt; + CurIcon->bpp = pCursorData->bpp; + CurIcon->hbmMask = pCursorData->hbmMask; + CurIcon->hbmColor = pCursorData->hbmColor; + CurIcon->hbmAlpha = pCursorData->hbmAlpha; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -956,41 +963,6 @@ NtUserSetCursorIconData( SetLastNtError(Status); goto done; } - - CurIcon->xHotspot = dataSafe.xHotspot; - CurIcon->yHotspot = dataSafe.yHotspot; - CurIcon->cx = dataSafe.cx; - CurIcon->cy = dataSafe.cy; - CurIcon->rt = dataSafe.rt; - CurIcon->bpp = dataSafe.bpp; - - if(!dataSafe.hbmMask) - { - ERR("NtUserSetCursorIconData was got no hbmMask.\n"); - EngSetLastError(ERROR_INVALID_PARAMETER); - goto done; - } - - CurIcon->hbmMask = BITMAP_CopyBitmap(dataSafe.hbmMask); - if(!CurIcon->hbmMask) - goto done; - GreSetObjectOwner(CurIcon->hbmMask, GDI_OBJ_HMGR_PUBLIC); - - if(dataSafe.hbmColor) - { - CurIcon->hbmColor = BITMAP_CopyBitmap(dataSafe.hbmColor); - if(!CurIcon->hbmColor) - goto done; - GreSetObjectOwner(CurIcon->hbmColor, GDI_OBJ_HMGR_PUBLIC); - } - - if(dataSafe.hbmAlpha) - { - CurIcon->hbmAlpha = BITMAP_CopyBitmap(dataSafe.hbmAlpha); - if(!CurIcon->hbmAlpha) - goto done; - GreSetObjectOwner(CurIcon->hbmAlpha, GDI_OBJ_HMGR_PUBLIC); - } if(pustrModule) { @@ -1002,30 +974,28 @@ NtUserSetCursorIconData( if(!NT_SUCCESS(Status)) goto done; } + + + if(!CurIcon->hbmMask) + { + ERR("NtUserSetCursorIconData was got no hbmMask.\n"); + EngSetLastError(ERROR_INVALID_PARAMETER); + goto done; + } + + GreSetObjectOwner(CurIcon->hbmMask, GDI_OBJ_HMGR_PUBLIC); + + if(CurIcon->hbmColor) + GreSetObjectOwner(CurIcon->hbmColor, GDI_OBJ_HMGR_PUBLIC); + + if(CurIcon->hbmAlpha) + GreSetObjectOwner(CurIcon->hbmAlpha, GDI_OBJ_HMGR_PUBLIC); Ret = TRUE; done: if(!Ret) { - if (CurIcon->hbmMask) - { - GreSetObjectOwner(CurIcon->hbmMask, GDI_OBJ_HMGR_POWNED); - GreDeleteObject(CurIcon->hbmMask); - CurIcon->hbmMask = NULL; - } - if (CurIcon->hbmColor) - { - GreSetObjectOwner(CurIcon->hbmColor, GDI_OBJ_HMGR_POWNED); - GreDeleteObject(CurIcon->hbmColor); - CurIcon->hbmColor = NULL; - } - if (CurIcon->hbmAlpha) - { - GreSetObjectOwner(CurIcon->hbmAlpha, GDI_OBJ_HMGR_POWNED); - GreDeleteObject(CurIcon->hbmAlpha); - CurIcon->hbmAlpha = NULL; - } if(!IS_INTRESOURCE(CurIcon->strName.Buffer)) ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING); if(CurIcon->ustrModule.Buffer) diff --git a/reactos/win32ss/user/ntuser/msgqueue.c b/reactos/win32ss/user/ntuser/msgqueue.c index 88514fa095a..ef090e1b80e 100644 --- a/reactos/win32ss/user/ntuser/msgqueue.c +++ b/reactos/win32ss/user/ntuser/msgqueue.c @@ -147,12 +147,13 @@ UserSetCursor( /* Call GDI to set the new screen cursor */ #ifdef NEW_CURSORICON GreSetPointerShape(hdcScreen, - NewCursor->hbmMask, - NewCursor->hbmColor, + NewCursor->hbmAlpha ? NULL : NewCursor->hbmMask, + NewCursor->hbmAlpha ? NewCursor->hbmAlpha : NewCursor->hbmColor, NewCursor->xHotspot, NewCursor->yHotspot, gpsi->ptCursor.x, - gpsi->ptCursor.y); + gpsi->ptCursor.y, + NewCursor->hbmAlpha ? SPS_ALPHA : 0); #else GreSetPointerShape(hdcScreen, NewCursor->IconInfo.hbmMask, @@ -160,7 +161,8 @@ UserSetCursor( NewCursor->IconInfo.xHotspot, NewCursor->IconInfo.yHotspot, gpsi->ptCursor.x, - gpsi->ptCursor.y); + gpsi->ptCursor.y, + 0); #endif } else /* Note: OldCursor != NewCursor so we have to hide cursor */ @@ -582,13 +584,16 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook { /* Call GDI to set the new screen cursor */ #ifdef NEW_CURSORICON - GreSetPointerShape(hdcScreen, - MessageQueue->CursorObject->hbmMask, - MessageQueue->CursorObject->hbmColor, - MessageQueue->CursorObject->xHotspot, - MessageQueue->CursorObject->yHotspot, - gpsi->ptCursor.x, - gpsi->ptCursor.y); + GreSetPointerShape(hdcScreen, + MessageQueue->CursorObject->hbmAlpha ? + NULL : MessageQueue->CursorObject->hbmMask, + MessageQueue->CursorObject->hbmAlpha ? + MessageQueue->CursorObject->hbmAlpha : MessageQueue->CursorObject->hbmColor, + MessageQueue->CursorObject->xHotspot, + MessageQueue->CursorObject->yHotspot, + gpsi->ptCursor.x, + gpsi->ptCursor.y, + MessageQueue->CursorObject->hbmAlpha ? SPS_ALPHA : 0); #else GreSetPointerShape(hdcScreen, MessageQueue->CursorObject->IconInfo.hbmMask, @@ -596,7 +601,8 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook MessageQueue->CursorObject->IconInfo.xHotspot, MessageQueue->CursorObject->IconInfo.yHotspot, gpsi->ptCursor.x, - gpsi->ptCursor.y); + gpsi->ptCursor.y, + 0); #endif } else GreMovePointer(hdcScreen, Msg->pt.x, Msg->pt.y); diff --git a/reactos/win32ss/user/user32/windows/cursoricon_new.c b/reactos/win32ss/user/user32/windows/cursoricon_new.c index 8bead53c55a..f79d6a1b731 100644 --- a/reactos/win32ss/user/user32/windows/cursoricon_new.c +++ b/reactos/win32ss/user/user32/windows/cursoricon_new.c @@ -906,24 +906,26 @@ CURSORICON_LoadFromFileW( hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1); if(!hCurIcon) - goto end_clean; + goto end_error; /* Tell win32k */ if(!NtUserSetCursorIconData(hCurIcon, NULL, NULL, &cursorData)) { NtUserDestroyCursor(hCurIcon, TRUE); - hCurIcon = NULL; + goto end_error; } - /* Clean up */ -end_clean: - DeleteObject(cursorData.hbmMask); - if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor); - if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha); - end: UnmapViewOfFile(bits); return hCurIcon; + + /* Clean up */ +end_error: + DeleteObject(cursorData.hbmMask); + if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor); + if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha); + + return NULL; } static @@ -1078,36 +1080,44 @@ CURSORICON_LoadImageW( if(!bStatus) goto done; + /* This is from resource */ + cursorData.CURSORF_flags = CURSORF_FROMRESOURCE; + /* Create the handle */ hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1); if(!hCurIcon) { - DeleteObject(cursorData.hbmMask); - if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor); - if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha); - goto done; + goto end_error; } /* Tell win32k */ if(fuLoad & LR_SHARED) + { + cursorData.CURSORF_flags |= CURSORF_LRSHARED; bStatus = NtUserSetCursorIconData(hCurIcon, &ustrModule, &ustrRsrc, &cursorData); + } else bStatus = NtUserSetCursorIconData(hCurIcon, NULL, NULL, &cursorData); if(!bStatus) { NtUserDestroyCursor(hCurIcon, TRUE); - hCurIcon = NULL; + goto end_error; } - - DeleteObject(cursorData.hbmMask); - if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor); - if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha); done: if(ustrModule.Buffer) HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); return hCurIcon; + +end_error: + if(ustrModule.Buffer) + HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); + DeleteObject(cursorData.hbmMask); + if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor); + if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha); + + return NULL; } static @@ -1912,21 +1922,24 @@ HICON WINAPI CreateIconFromResourceEx( hIcon = NtUserxCreateEmptyCurObject(fIcon ? 0 : 1); if(!hIcon) - return NULL; + goto end_error; if(!NtUserSetCursorIconData(hIcon, NULL, NULL, &cursorData)) { ERR("NtUserSetCursorIconData failed.\n"); NtUserDestroyCursor(hIcon, TRUE); - hIcon = NULL; + goto end_error; } + return hIcon; + /* Clean up */ +end_error: DeleteObject(cursorData.hbmMask); if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor); if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha); - return hIcon; + return NULL; } HICON WINAPI CreateIconIndirect( @@ -1944,22 +1957,25 @@ HICON WINAPI CreateIconIndirect( hiconRet = NtUserxCreateEmptyCurObject(piconinfo->fIcon ? 0 : 1); if(!hiconRet) - return NULL; + goto end_error; if(!NtUserSetCursorIconData(hiconRet, NULL, NULL, &cursorData)) { NtUserDestroyCursor(hiconRet, FALSE); - hiconRet = NULL; + goto end_error; } + TRACE("Returning 0x%08x.\n", hiconRet); + + return hiconRet; + +end_error: /* Clean up */ DeleteObject(cursorData.hbmMask); if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor); if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha); - TRACE("Returning 0x%08x.\n", hiconRet); - - return hiconRet; + return NULL; } HCURSOR WINAPI CreateCursor(