- 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
This commit is contained in:
Jérôme Gardou 2012-11-10 15:56:42 +00:00
parent cde9a5f895
commit 6f481467d5
6 changed files with 149 additions and 118 deletions

View file

@ -232,29 +232,51 @@ IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest)
/* Blt the pointer on the screen. */ /* Blt the pointer on the screen. */
if (pgp->psurfColor) if (pgp->psurfColor)
{ {
IntEngBitBlt(psoDest, if(!(pgp->flags & SPS_ALPHA))
&pgp->psurfMask->SurfObj, {
NULL, IntEngBitBlt(psoDest,
NULL, &pgp->psurfMask->SurfObj,
NULL, NULL,
&rclSurf, NULL,
(POINTL*)&rclPointer, NULL,
NULL, &rclSurf,
NULL, (POINTL*)&rclPointer,
NULL, NULL,
ROP4_FROM_INDEX(R3_OPINDEX_SRCAND)); NULL,
NULL,
ROP4_SRCAND);
IntEngBitBlt(psoDest, IntEngBitBlt(psoDest,
&pgp->psurfColor->SurfObj, &pgp->psurfColor->SurfObj,
NULL, NULL,
NULL, NULL,
NULL, NULL,
&rclSurf, &rclSurf,
(POINTL*)&rclPointer, (POINTL*)&rclPointer,
NULL, NULL,
NULL, NULL,
NULL, NULL,
ROP4_FROM_INDEX(R3_OPINDEX_SRCINVERT)); 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 else
{ {
@ -352,7 +374,15 @@ EngSetPointerShape(
if (psoColor) if (psoColor)
{ {
/* Color bitmap must have the same format as the dest surface */ /* 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 */ /* Create a bitmap to copy the color bitmap to */
hbmColor = EngCreateBitmap(psoColor->sizlBitmap, hbmColor = EngCreateBitmap(psoColor->sizlBitmap,
@ -452,6 +482,7 @@ EngSetPointerShape(
pgp->HotSpot.x = xHot; pgp->HotSpot.x = xHot;
pgp->HotSpot.y = yHot; pgp->HotSpot.y = yHot;
pgp->Size = sizel; pgp->Size = sizel;
pgp->flags = fl;
if (x != -1) if (x != -1)
{ {
@ -598,12 +629,12 @@ GreSetPointerShape(
LONG xHot, LONG xHot,
LONG yHot, LONG yHot,
LONG x, LONG x,
LONG y) LONG y,
FLONG fl)
{ {
PDC pdc; PDC pdc;
PSURFACE psurf, psurfMask, psurfColor; PSURFACE psurf, psurfMask, psurfColor;
EXLATEOBJ exlo; EXLATEOBJ exlo;
FLONG fl = 0;
ULONG ulResult = 0; ULONG ulResult = 0;
pdc = DC_LockDc(hdc); pdc = DC_LockDc(hdc);
@ -629,7 +660,10 @@ GreSetPointerShape(
if (hbmMask) if (hbmMask)
psurfMask = SURFACE_ShareLockSurface(hbmMask); psurfMask = SURFACE_ShareLockSurface(hbmMask);
else else
{
ASSERT(fl & SPS_ALPHA);
psurfMask = NULL; psurfMask = NULL;
}
/* Check for color bitmap */ /* Check for color bitmap */
if (hbmColor) if (hbmColor)
@ -645,6 +679,9 @@ GreSetPointerShape(
} }
else else
psurfColor = NULL; 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 */ /* Call the driver or eng function */
ulResult = IntEngSetPointerShape(&psurf->SurfObj, ulResult = IntEngSetPointerShape(&psurf->SurfObj,

View file

@ -12,7 +12,8 @@ GreSetPointerShape(
LONG xHot, LONG xHot,
LONG yHot, LONG yHot,
LONG x, LONG x,
LONG y); LONG y,
FLONG fl);
VOID VOID
NTAPI NTAPI

View file

@ -34,6 +34,7 @@ typedef struct _GDIPOINTER /* should stay private to ENG? No, part of PDEVOBJ ak
SURFACE *psurfColor; SURFACE *psurfColor;
SURFACE *psurfMask; SURFACE *psurfMask;
SURFACE *psurfSave; SURFACE *psurfSave;
FLONG flags;
/* Public pointer information */ /* Public pointer information */
RECTL Exclude; /* Required publicly for SPS_ACCEPT_EXCLUDE */ RECTL Exclude; /* Required publicly for SPS_ACCEPT_EXCLUDE */

View file

@ -923,7 +923,6 @@ NtUserSetCursorIconData(
PCURICON_OBJECT CurIcon; PCURICON_OBJECT CurIcon;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
BOOL Ret = FALSE; BOOL Ret = FALSE;
CURSORDATA dataSafe;
TRACE("Enter NtUserSetCursorIconData\n"); TRACE("Enter NtUserSetCursorIconData\n");
@ -943,7 +942,15 @@ NtUserSetCursorIconData(
_SEH2_TRY _SEH2_TRY
{ {
ProbeForRead(pCursorData, sizeof(*pCursorData), 1); 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) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -956,41 +963,6 @@ NtUserSetCursorIconData(
SetLastNtError(Status); SetLastNtError(Status);
goto done; 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) if(pustrModule)
{ {
@ -1002,30 +974,28 @@ NtUserSetCursorIconData(
if(!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
goto done; 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; Ret = TRUE;
done: done:
if(!Ret) 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)) if(!IS_INTRESOURCE(CurIcon->strName.Buffer))
ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING); ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING);
if(CurIcon->ustrModule.Buffer) if(CurIcon->ustrModule.Buffer)

View file

@ -147,12 +147,13 @@ UserSetCursor(
/* Call GDI to set the new screen cursor */ /* Call GDI to set the new screen cursor */
#ifdef NEW_CURSORICON #ifdef NEW_CURSORICON
GreSetPointerShape(hdcScreen, GreSetPointerShape(hdcScreen,
NewCursor->hbmMask, NewCursor->hbmAlpha ? NULL : NewCursor->hbmMask,
NewCursor->hbmColor, NewCursor->hbmAlpha ? NewCursor->hbmAlpha : NewCursor->hbmColor,
NewCursor->xHotspot, NewCursor->xHotspot,
NewCursor->yHotspot, NewCursor->yHotspot,
gpsi->ptCursor.x, gpsi->ptCursor.x,
gpsi->ptCursor.y); gpsi->ptCursor.y,
NewCursor->hbmAlpha ? SPS_ALPHA : 0);
#else #else
GreSetPointerShape(hdcScreen, GreSetPointerShape(hdcScreen,
NewCursor->IconInfo.hbmMask, NewCursor->IconInfo.hbmMask,
@ -160,7 +161,8 @@ UserSetCursor(
NewCursor->IconInfo.xHotspot, NewCursor->IconInfo.xHotspot,
NewCursor->IconInfo.yHotspot, NewCursor->IconInfo.yHotspot,
gpsi->ptCursor.x, gpsi->ptCursor.x,
gpsi->ptCursor.y); gpsi->ptCursor.y,
0);
#endif #endif
} }
else /* Note: OldCursor != NewCursor so we have to hide cursor */ 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 */ /* Call GDI to set the new screen cursor */
#ifdef NEW_CURSORICON #ifdef NEW_CURSORICON
GreSetPointerShape(hdcScreen, GreSetPointerShape(hdcScreen,
MessageQueue->CursorObject->hbmMask, MessageQueue->CursorObject->hbmAlpha ?
MessageQueue->CursorObject->hbmColor, NULL : MessageQueue->CursorObject->hbmMask,
MessageQueue->CursorObject->xHotspot, MessageQueue->CursorObject->hbmAlpha ?
MessageQueue->CursorObject->yHotspot, MessageQueue->CursorObject->hbmAlpha : MessageQueue->CursorObject->hbmColor,
gpsi->ptCursor.x, MessageQueue->CursorObject->xHotspot,
gpsi->ptCursor.y); MessageQueue->CursorObject->yHotspot,
gpsi->ptCursor.x,
gpsi->ptCursor.y,
MessageQueue->CursorObject->hbmAlpha ? SPS_ALPHA : 0);
#else #else
GreSetPointerShape(hdcScreen, GreSetPointerShape(hdcScreen,
MessageQueue->CursorObject->IconInfo.hbmMask, 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.xHotspot,
MessageQueue->CursorObject->IconInfo.yHotspot, MessageQueue->CursorObject->IconInfo.yHotspot,
gpsi->ptCursor.x, gpsi->ptCursor.x,
gpsi->ptCursor.y); gpsi->ptCursor.y,
0);
#endif #endif
} else } else
GreMovePointer(hdcScreen, Msg->pt.x, Msg->pt.y); GreMovePointer(hdcScreen, Msg->pt.x, Msg->pt.y);

View file

@ -906,24 +906,26 @@ CURSORICON_LoadFromFileW(
hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1); hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1);
if(!hCurIcon) if(!hCurIcon)
goto end_clean; goto end_error;
/* Tell win32k */ /* Tell win32k */
if(!NtUserSetCursorIconData(hCurIcon, NULL, NULL, &cursorData)) if(!NtUserSetCursorIconData(hCurIcon, NULL, NULL, &cursorData))
{ {
NtUserDestroyCursor(hCurIcon, TRUE); 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: end:
UnmapViewOfFile(bits); UnmapViewOfFile(bits);
return hCurIcon; return hCurIcon;
/* Clean up */
end_error:
DeleteObject(cursorData.hbmMask);
if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
return NULL;
} }
static static
@ -1078,36 +1080,44 @@ CURSORICON_LoadImageW(
if(!bStatus) if(!bStatus)
goto done; goto done;
/* This is from resource */
cursorData.CURSORF_flags = CURSORF_FROMRESOURCE;
/* Create the handle */ /* Create the handle */
hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1); hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1);
if(!hCurIcon) if(!hCurIcon)
{ {
DeleteObject(cursorData.hbmMask); goto end_error;
if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
goto done;
} }
/* Tell win32k */ /* Tell win32k */
if(fuLoad & LR_SHARED) if(fuLoad & LR_SHARED)
{
cursorData.CURSORF_flags |= CURSORF_LRSHARED;
bStatus = NtUserSetCursorIconData(hCurIcon, &ustrModule, &ustrRsrc, &cursorData); bStatus = NtUserSetCursorIconData(hCurIcon, &ustrModule, &ustrRsrc, &cursorData);
}
else else
bStatus = NtUserSetCursorIconData(hCurIcon, NULL, NULL, &cursorData); bStatus = NtUserSetCursorIconData(hCurIcon, NULL, NULL, &cursorData);
if(!bStatus) if(!bStatus)
{ {
NtUserDestroyCursor(hCurIcon, TRUE); NtUserDestroyCursor(hCurIcon, TRUE);
hCurIcon = NULL; goto end_error;
} }
DeleteObject(cursorData.hbmMask);
if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
done: done:
if(ustrModule.Buffer) if(ustrModule.Buffer)
HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); HeapFree(GetProcessHeap(), 0, ustrModule.Buffer);
return hCurIcon; 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 static
@ -1912,21 +1922,24 @@ HICON WINAPI CreateIconFromResourceEx(
hIcon = NtUserxCreateEmptyCurObject(fIcon ? 0 : 1); hIcon = NtUserxCreateEmptyCurObject(fIcon ? 0 : 1);
if(!hIcon) if(!hIcon)
return NULL; goto end_error;
if(!NtUserSetCursorIconData(hIcon, NULL, NULL, &cursorData)) if(!NtUserSetCursorIconData(hIcon, NULL, NULL, &cursorData))
{ {
ERR("NtUserSetCursorIconData failed.\n"); ERR("NtUserSetCursorIconData failed.\n");
NtUserDestroyCursor(hIcon, TRUE); NtUserDestroyCursor(hIcon, TRUE);
hIcon = NULL; goto end_error;
} }
return hIcon;
/* Clean up */ /* Clean up */
end_error:
DeleteObject(cursorData.hbmMask); DeleteObject(cursorData.hbmMask);
if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor); if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha); if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
return hIcon; return NULL;
} }
HICON WINAPI CreateIconIndirect( HICON WINAPI CreateIconIndirect(
@ -1944,22 +1957,25 @@ HICON WINAPI CreateIconIndirect(
hiconRet = NtUserxCreateEmptyCurObject(piconinfo->fIcon ? 0 : 1); hiconRet = NtUserxCreateEmptyCurObject(piconinfo->fIcon ? 0 : 1);
if(!hiconRet) if(!hiconRet)
return NULL; goto end_error;
if(!NtUserSetCursorIconData(hiconRet, NULL, NULL, &cursorData)) if(!NtUserSetCursorIconData(hiconRet, NULL, NULL, &cursorData))
{ {
NtUserDestroyCursor(hiconRet, FALSE); NtUserDestroyCursor(hiconRet, FALSE);
hiconRet = NULL; goto end_error;
} }
TRACE("Returning 0x%08x.\n", hiconRet);
return hiconRet;
end_error:
/* Clean up */ /* Clean up */
DeleteObject(cursorData.hbmMask); DeleteObject(cursorData.hbmMask);
if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor); if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor);
if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha); if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha);
TRACE("Returning 0x%08x.\n", hiconRet); return NULL;
return hiconRet;
} }
HCURSOR WINAPI CreateCursor( HCURSOR WINAPI CreateCursor(