diff --git a/reactos/win32ss/include/ntuser.h b/reactos/win32ss/include/ntuser.h index be603583838..c89f8523295 100644 --- a/reactos/win32ss/include/ntuser.h +++ b/reactos/win32ss/include/ntuser.h @@ -521,18 +521,24 @@ typedef struct _CLS INT cbclsExtra; INT cbwndExtra; HINSTANCE hModule; +#ifdef NEW_CURSORICON + struct _CURICON_OBJECT* spicn; + struct _CURICON_OBJECT* spcur; +#else HANDLE hIcon; /* FIXME - Use pointer! */ - //PCURSOR spicn; HANDLE hCursor; /* FIXME - Use pointer! */ - //PCURSOR spcur; +#endif HBRUSH hbrBackground; PWSTR lpszMenuName; // kernel use PSTR lpszAnsiClassName; // " +#ifdef NEW_CURSORICON + struct _CURICON_OBJECT* spicnSm; +#else HANDLE hIconSm; /* FIXME - Use pointer! */ - //PCURSOR spicnSm; //// ReactOS dosn't suppot cache icons. HICON hIconSmIntern; /* Internal small icon, derived from hIcon */ +#endif //// UINT Unicode : 1; // !CSF_ANSIPROC UINT Global : 1; // CS_GLOBALCLASS or CSF_SERVERSIDEPROC diff --git a/reactos/win32ss/user/ntuser/class.c b/reactos/win32ss/user/ntuser/class.c index f14071e3ea8..dfe3e9c2110 100644 --- a/reactos/win32ss/user/ntuser/class.c +++ b/reactos/win32ss/user/ntuser/class.c @@ -245,8 +245,17 @@ IntDestroyClass(IN OUT PCLS Class) IntFreeClassMenuName(Class); } +#ifdef NEW_CURSORICON + if (Class->spicn) + UserDereferenceObject(Class->spicn); + if (Class->spicnSm) + UserDereferenceObject(Class->spicnSm); + if (Class->spcur) + UserDereferenceObject(Class->spcur); +#else if (Class->hIconSmIntern) IntClassDestroyIcon(Class->hIconSmIntern); +#endif pDesk = Class->rpdeskParent; Class->rpdeskParent = NULL; @@ -587,11 +596,22 @@ IntGetClassForDesktop(IN OUT PCLS BaseClass, Class = DesktopHeapAlloc(Desktop, ClassSize); + if (Class != NULL) { /* Simply clone the class */ RtlCopyMemory( Class, BaseClass, ClassSize); +#ifdef NEW_CURSORICON + /* Reference our objects */ + if (Class->spcur) + UserReferenceObject(Class->spcur); + if (Class->spicn) + UserReferenceObject(Class->spicn); + if (Class->spicnSm) + UserReferenceObject(Class->spicnSm); +#endif + TRACE("Clone Class 0x%p hM 0x%p\n %S\n",Class, Class->hModule, Class->lpszClientUnicodeMenuName); /* Restore module address if default user class Ref: Bug 4778 */ @@ -1009,10 +1029,15 @@ IntCreateClass(IN CONST WNDCLASSEXW* lpwcx, Class->cbclsExtra = lpwcx->cbClsExtra; Class->cbwndExtra = lpwcx->cbWndExtra; Class->hModule = lpwcx->hInstance; - //// FIXME handles to pointers +#ifdef NEW_CURSORICON + Class->spicn = lpwcx->hIcon ? UserGetCurIconObject(lpwcx->hIcon) : NULL; + Class->spcur = lpwcx->hCursor ? UserGetCurIconObject(lpwcx->hCursor) : NULL; + Class->spicnSm = lpwcx->hIconSm ? UserGetCurIconObject(lpwcx->hIconSm) : NULL; +#else Class->hIcon = lpwcx->hIcon; Class->hIconSm = lpwcx->hIconSm; Class->hCursor = lpwcx->hCursor; +#endif //// Class->hbrBackground = lpwcx->hbrBackground; @@ -1726,13 +1751,7 @@ IntSetClassMenuName(IN PCLS Class, return Ret; } -//// Do this for now in anticipation of new cursor icon code. #ifndef NEW_CURSORICON -BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT, PPROCESSINFO); -#else -BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT, BOOLEAN); -#endif - BOOL FASTCALL IntClassDestroyIcon(HANDLE hCurIcon) { @@ -1745,19 +1764,15 @@ IntClassDestroyIcon(HANDLE hCurIcon) ERR("hCurIcon was not found!\n"); return FALSE; } -#ifndef NEW_CURSORICON - Ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process()); - /* Note: IntDestroyCurIconObject will remove our reference for us! */ -#else /* Note: IntDestroyCurIconObject will remove our reference for us! */ Ret = IntDestroyCurIconObject(CurIcon, TRUE); -#endif if (!Ret) { ERR("hCurIcon was not Destroyed!\n"); } return Ret; } +#endif ULONG_PTR UserSetClassLongPtr(IN PCLS Class, @@ -1766,7 +1781,9 @@ UserSetClassLongPtr(IN PCLS Class, IN BOOL Ansi) { ULONG_PTR Ret = 0; +#ifndef NEW_CURSORICON HANDLE hIconSmIntern = NULL; +#endif /* NOTE: For GCLP_MENUNAME and GCW_ATOM this function may raise an exception! */ @@ -1838,6 +1855,54 @@ UserSetClassLongPtr(IN PCLS Class, } break; +#ifdef NEW_CURSORICON + case GCLP_HCURSOR: + { + PCURICON_OBJECT NewCursor = NULL; + + if (NewLong) + { + NewCursor = UserGetCurIconObject((HCURSOR)NewLong); + if (!NewCursor) + { + EngSetLastError(ERROR_INVALID_CURSOR_HANDLE); + return 0; + } + } + + if (Class->spcur) + { + Ret = (ULONG_PTR)UserHMGetHandle(Class->spcur); + UserDereferenceObject(Class->spcur); + } + else + { + Ret = 0; + } + + if (Ret == NewLong) + { + /* It's a nop */ + return Ret; + } + + Class->spcur = NewCursor; + + /* Update the clones */ + Class = Class->pclsClone; + while (Class != NULL) + { + if (Class->spcur) + UserDereferenceObject(Class->spcur); + if (NewCursor) + UserReferenceObject(NewCursor); + Class->spcur = NewCursor; + Class = Class->pclsNext; + } + + break; + } +#else case GCLP_HCURSOR: /* FIXME: Get handle from pointer to CURSOR object */ Ret = (ULONG_PTR)Class->hCursor; @@ -1851,6 +1916,7 @@ UserSetClassLongPtr(IN PCLS Class, Class = Class->pclsNext; } break; +#endif // MSDN: // hIconSm, A handle to a small icon that is associated with the window class. @@ -1858,6 +1924,88 @@ UserSetClassLongPtr(IN PCLS Class, // the hIcon member for an icon of the appropriate size to use as the small icon. // case GCLP_HICON: +#ifdef NEW_CURSORICON + { + PCURICON_OBJECT NewIcon = NULL; + PCURICON_OBJECT NewSmallIcon = NULL; + + if (NewLong) + { + NewIcon = UserGetCurIconObject((HCURSOR)NewLong); + if (!NewIcon) + { + EngSetLastError(ERROR_INVALID_ICON_HANDLE); + return 0; + } + } + + if (Class->spicn) + { + Ret = (ULONG_PTR)UserHMGetHandle(Class->spicn); + UserDereferenceObject(Class->spicn); + } + else + { + Ret = 0; + } + + if (Ret == NewLong) + { + /* It's a nop */ + return Ret; + } + + if (Ret && (Class->CSF_flags & CSF_CACHEDSMICON)) + { + /* We will change the small icon */ + UserDereferenceObject(Class->spicnSm); + Class->spicnSm = NULL; + Class->CSF_flags &= ~CSF_CACHEDSMICON; + } + + if (NewLong && !Class->spicnSm) + { + /* Create the new small icon from the new large(?) one */ + HICON SmallIconHandle = co_IntCopyImage( + (HICON)NewLong, + IMAGE_ICON, + UserGetSystemMetrics( SM_CXSMICON ), + UserGetSystemMetrics( SM_CYSMICON ), + 0); + if (SmallIconHandle) + { + /* So use it */ + NewSmallIcon = Class->spicnSm = UserGetCurIconObject(SmallIconHandle); + /* Let the handle go, we have the reference on the object */ + NtUserDestroyCursor(SmallIconHandle, FALSE); + Class->CSF_flags |= CSF_CACHEDSMICON; + } + } + + Class->spicn = NewIcon; + + /* Update the clones */ + Class = Class->pclsClone; + while (Class != NULL) + { + if (Class->spicn) + UserDereferenceObject(Class->spicn); + if (NewIcon) + UserReferenceObject(NewIcon); + Class->spicn = NewIcon; + if (NewSmallIcon) + { + if (Class->spicnSm) + UserDereferenceObject(Class->spicnSm); + UserReferenceObject(NewSmallIcon); + Class->spicnSm = NewSmallIcon; + Class->CSF_flags |= CSF_CACHEDSMICON; + } + Class = Class->pclsNext; + } + break; + } +#else /* FIXME: Get handle from pointer to ICON object */ Ret = (ULONG_PTR)Class->hIcon; if (Class->hIcon == (HANDLE)NewLong) break; @@ -1885,8 +2033,51 @@ UserSetClassLongPtr(IN PCLS Class, Class = Class->pclsNext; } break; +#endif case GCLP_HICONSM: +#ifdef NEW_CURSORICON + { + PCURICON_OBJECT NewSmallIcon = NULL; + + if (NewLong) + { + NewSmallIcon = UserGetCurIconObject((HCURSOR)NewLong); + if (!NewSmallIcon) + { + EngSetLastError(ERROR_INVALID_ICON_HANDLE); + return 0; + } + } + + if (Class->spicnSm) + { + Ret = (ULONG_PTR)UserHMGetHandle(Class->spicnSm); + UserDereferenceObject(Class->spicnSm); + } + else + { + Ret = 0; + } + + Class->CSF_flags &= ~CSF_CACHEDSMICON; + Class->spicnSm = NewSmallIcon; + + /* Update the clones */ + Class = Class->pclsClone; + while (Class != NULL) + { + if (Class->spicnSm) + UserDereferenceObject(Class->spicnSm); + if (NewSmallIcon) + UserReferenceObject(NewSmallIcon); + Class->CSF_flags &= ~CSF_CACHEDSMICON; + Class->spicnSm = NewSmallIcon; + Class = Class->pclsNext; + } + } + break; +#else /* FIXME: Get handle from pointer to ICON object */ Ret = (ULONG_PTR)Class->hIconSm; if (Class->hIconSm == (HANDLE)NewLong) break; @@ -1920,6 +2111,7 @@ UserSetClassLongPtr(IN PCLS Class, Class = Class->pclsNext; } break; +#endif case GCLP_HMODULE: Ret = (ULONG_PTR)Class->hModule; @@ -2011,8 +2203,16 @@ UserGetClassInfo(IN PCLS Class, lpwcx->cbClsExtra = Class->cbclsExtra; lpwcx->cbWndExtra = Class->cbwndExtra; +#ifdef NEW_CURSORICON + lpwcx->hIcon = Class->spicn ? UserHMGetHandle(Class->spicn) : NULL; + lpwcx->hCursor = Class->spcur ? UserHMGetHandle(Class->spcur) : NULL; + lpwcx->hIconSm = Class->spicnSm ? UserHMGetHandle(Class->spicnSm) : NULL; +#else lpwcx->hIcon = Class->hIcon; /* FIXME: Get handle from pointer */ lpwcx->hCursor = Class->hCursor; /* FIXME: Get handle from pointer */ + /* FIXME: Get handle from pointer */ + lpwcx->hIconSm = Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern; +#endif lpwcx->hbrBackground = Class->hbrBackground; /* Copy non-string to user first. */ @@ -2042,9 +2242,6 @@ UserGetClassInfo(IN PCLS Class, /* FIXME: Return the string? Okay! This is performed in User32! */ //lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->atomClassName); - /* FIXME: Get handle from pointer */ - lpwcx->hIconSm = Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern; - return TRUE; } diff --git a/reactos/win32ss/user/ntuser/cursoricon.h b/reactos/win32ss/user/ntuser/cursoricon.h index c6b998a8d52..d62453f2b9d 100644 --- a/reactos/win32ss/user/ntuser/cursoricon.h +++ b/reactos/win32ss/user/ntuser/cursoricon.h @@ -41,6 +41,12 @@ typedef struct tagACON C_ASSERT(FIELD_OFFSET(ACON, cpcur) == FIELD_OFFSET(CURICON_OBJECT, xHotspot)); +BOOLEAN +IntDestroyCurIconObject(PVOID Object); + +VOID FASTCALL +IntCleanupCurIconCache(PPROCESSINFO Win32Process); + #else typedef struct tagCURICON_PROCESS @@ -62,6 +68,9 @@ typedef struct _CURICON_OBJECT BYTE Shadow; ICONINFO IconInfo; } CURICON_OBJECT, *PCURICON_OBJECT; +BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi); +BOOL FASTCALL IntDestroyCursor(HANDLE hCurIcon, BOOL bForce); +HCURSOR FASTCALL IntSetCursor(HCURSOR hCursor); #endif typedef struct _CURSORACCELERATION_INFO @@ -112,9 +121,6 @@ PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon); BOOL UserSetCursorPos( INT x, INT y, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook); BOOL APIENTRY UserClipCursor(RECTL *prcl); PSYSTEM_CURSORINFO IntGetSysCursorInfo(VOID); -HCURSOR FASTCALL IntSetCursor(HCURSOR hCursor); -BOOL FASTCALL IntDestroyCursor(HANDLE hCurIcon, BOOL bForce); -BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi); #define IntReleaseCurIconObject(CurIconObj) \ UserDereferenceObject(CurIconObj) diff --git a/reactos/win32ss/user/ntuser/cursoricon_new.c b/reactos/win32ss/user/ntuser/cursoricon_new.c index 40e28458ea2..9beedbaab22 100644 --- a/reactos/win32ss/user/ntuser/cursoricon_new.c +++ b/reactos/win32ss/user/ntuser/cursoricon_new.c @@ -133,7 +133,7 @@ IntCreateCurIconHandle(BOOLEAN Animated) CurIcon = UserCreateObject( gHandleTable, NULL, - NULL, + GetW32ThreadInfo(), &hCurIcon, TYPE_CURSOR, Animated ? sizeof(ACON) : sizeof(CURICON_OBJECT)); @@ -149,35 +149,11 @@ IntCreateCurIconHandle(BOOLEAN Animated) return hCurIcon; } -BOOLEAN FASTCALL -IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOLEAN bForce) +BOOLEAN +IntDestroyCurIconObject(PVOID Object) { - if(CurIcon->CURSORF_flags & CURSORF_CURRENT) - { - /* Mark the object as destroyed, and fail, as per tests */ - TRACE("Cursor is current, marking as destroyed.\n"); - UserDeleteObject(CurIcon->head.h, TYPE_CURSOR); - return FALSE; - } - - if(CurIcon->head.ppi != PsGetCurrentProcessWin32Process()) - { - /* This object doesn't belong to the current process */ - WARN("Trying to delete foreign cursor!\n"); - UserDereferenceObject(CurIcon); - EngSetLastError(ERROR_DESTROY_OBJECT_OF_OTHER_THREAD); - return FALSE; - } + PCURICON_OBJECT CurIcon = Object; - /* Do not destroy it if it is shared. (And we're not forced to) */ - if((CurIcon->CURSORF_flags & CURSORF_LRSHARED) && !bForce) - { - /* Tests show this is a valid call */ - WARN("Trying to destroy shared cursor!\n"); - UserDereferenceObject(CurIcon); - return TRUE; - } - if(!(CurIcon->CURSORF_flags & CURSORF_ACON)) { HBITMAP bmpMask = CurIcon->hbmMask; @@ -210,103 +186,57 @@ IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOLEAN bForce) UINT i; for(i = 0; i < AniCurIcon->cpcur; i++) - IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE); + IntDestroyCurIconObject(AniCurIcon->aspcur[i]); ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR); } if (CurIcon->CURSORF_flags & CURSORF_LRSHARED) { + PPROCESSINFO ppi; + if (!IS_INTRESOURCE(CurIcon->strName.Buffer)) ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING); if (CurIcon->atomModName) RtlDeleteAtomFromAtomTable(gAtomTable, CurIcon->atomModName); CurIcon->strName.Buffer = NULL; CurIcon->atomModName = 0; + + /* Try finding it in its process cache */ + ppi = CurIcon->head.ppi; + if (ppi->pCursorCache == CurIcon) + ppi->pCursorCache = CurIcon->pcurNext; + else + { + PCURICON_OBJECT CacheCurIcon= ppi->pCursorCache; + while (CacheCurIcon) + { + if (CacheCurIcon->pcurNext == CurIcon) + { + CacheCurIcon->pcurNext = CurIcon->pcurNext; + break; + } + CacheCurIcon = CacheCurIcon->pcurNext; + } + } } - /* We were given a pointer, no need to keep the reference any longer! */ - UserDereferenceObject(CurIcon); - return UserDeleteObject(CurIcon->head.h, TYPE_CURSOR); + return TRUE; } VOID FASTCALL -IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process) +IntCleanupCurIconCache(PPROCESSINFO Win32Process) { PCURICON_OBJECT CurIcon; /* Run through the list of icon objects */ - while(Win32Process->pCursorCache) + while (Win32Process->pCursorCache) { CurIcon = Win32Process->pCursorCache; Win32Process->pCursorCache = CurIcon->pcurNext; - /* One ref for the handle, one for the list, - * and potentially one from an other process via SetCursor */ - ASSERT(CurIcon->head.cLockObj <= 3); - IntDestroyCurIconObject(CurIcon, TRUE); + UserDereferenceObject(CurIcon); } } -HCURSOR FASTCALL -IntSetCursor( - HCURSOR hCursor) -{ - PCURICON_OBJECT pcurOld, pcurNew; - HCURSOR hOldCursor = NULL; - - if (hCursor) - { - pcurNew = UserGetCurIconObject(hCursor); - if (!pcurNew) - { - EngSetLastError(ERROR_INVALID_CURSOR_HANDLE); - goto leave; - } - pcurNew->CURSORF_flags |= CURSORF_CURRENT; - } - else - { - pcurNew = NULL; - } - - pcurOld = UserSetCursor(pcurNew, FALSE); - if (pcurOld) - { - hOldCursor = pcurOld->head.h; - pcurOld->CURSORF_flags &= ~CURSORF_CURRENT; - if(UserObjectInDestroy(hOldCursor)) - { - /* Destroy it once and for all */ - IntDestroyCurIconObject(pcurOld, TRUE); - hOldCursor = NULL; - } - else - { - UserDereferenceObject(pcurOld); - } - } -leave: - return hOldCursor; -} - -BOOL FASTCALL -IntDestroyCursor( - HANDLE hCurIcon, - BOOL bForce) -{ - PCURICON_OBJECT CurIcon; - BOOL ret; - - if (!(CurIcon = UserGetCurIconObject(hCurIcon))) - { - return(FALSE); - } - - ret = IntDestroyCurIconObject(CurIcon, bForce); - /* Note: IntDestroyCurIconObject will remove our reference for us! */ - - return ret; -} - /* * @implemented */ @@ -690,27 +620,56 @@ NtUserDestroyCursor( _In_ HANDLE hCurIcon, _In_ BOOL bForce) { - PCURICON_OBJECT CurIcon; BOOL ret; - DECLARE_RETURN(BOOL); TRACE("Enter NtUserDestroyCursorIcon\n"); UserEnterExclusive(); - if (!(CurIcon = UserGetCurIconObject(hCurIcon))) + if (!bForce) { - RETURN(FALSE); + /* Maybe we have good reasons not to destroy this object */ + PCURICON_OBJECT CurIcon = UserGetCurIconObject(hCurIcon); + ULONG Flags; + if (!CurIcon) + { + ret = FALSE; + goto leave; + } + + if (CurIcon->head.ppi != PsGetCurrentProcessWin32Process()) + { + /* No way, you're not touching my cursor */ + ret = FALSE; + UserDereferenceObject(CurIcon); + goto leave; + } + + Flags = CurIcon->CURSORF_flags; + UserDereferenceObject(CurIcon); + + if (Flags & CURSORF_CURRENT) + { + WARN("Trying to delete current cursor!\n"); + ret = FALSE; + goto leave; + } + + if (Flags & CURSORF_LRSHARED) + { + WARN("Trying to delete shared cursor.\n"); + /* This one is not an error */ + ret = TRUE; + goto leave; + } } - ret = IntDestroyCurIconObject(CurIcon, bForce); - /* Note: IntDestroyCurIconObject will remove our reference for us! */ + /* Destroy the handle */ + ret = UserDeleteObject(hCurIcon, TYPE_CURSOR); - RETURN(ret); - -CLEANUP: - TRACE("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_); +leave: + TRACE("Leave NtUserDestroyCursorIcon, ret=%i\n", ret); UserLeave(); - END_CLEANUP; + return ret; } @@ -891,18 +850,8 @@ NtUserSetCursor( pcurOld = UserSetCursor(pcurNew, FALSE); if (pcurOld) { - hOldCursor = pcurOld->head.h; pcurOld->CURSORF_flags &= ~CURSORF_CURRENT; - if(UserObjectInDestroy(hOldCursor)) - { - /* Destroy it once and for all */ - IntDestroyCurIconObject(pcurOld, TRUE); - hOldCursor = NULL; - } - else - { - UserDereferenceObject(pcurOld); - } + UserDereferenceObject(pcurOld); } leave: @@ -1088,7 +1037,7 @@ done: for(i = 0; i < numFrames; i++) { if(AniCurIcon->aspcur[i]) - IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE); + IntDestroyCurIconObject(AniCurIcon->aspcur[i]); } AniCurIcon->cicur = 0; AniCurIcon->cpcur = 0; diff --git a/reactos/win32ss/user/ntuser/defwnd.c b/reactos/win32ss/user/ntuser/defwnd.c index b4c00df7ea0..4ca3b2da0a1 100644 --- a/reactos/win32ss/user/ntuser/defwnd.c +++ b/reactos/win32ss/user/ntuser/defwnd.c @@ -387,7 +387,11 @@ DefWndDoSizeMove(PWND pwnd, WORD wParam) RECT sizingRect, mouseRect, origRect, unmodRect; HDC hdc; LONG hittest = (LONG)(wParam & 0x0f); +#ifdef NEW_CURSORICON + PCURICON_OBJECT DragCursor = NULL, OldCursor = NULL; +#else HCURSOR hDragCursor = 0, hOldCursor = 0; +#endif POINT minTrack, maxTrack; POINT capturePoint, pt; ULONG Style, ExStyle; @@ -495,13 +499,35 @@ DefWndDoSizeMove(PWND pwnd, WORD wParam) } hdc = UserGetDCEx( pWndParent, 0, DCX_CACHE ); - +#ifdef NEW_CURSORICON + if (iconic) + { + DragCursor = pwnd->pcls->spicn; + if (DragCursor) + { + UserReferenceObject(DragCursor); + } + else + { + HCURSOR CursorHandle = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 ); + if (CursorHandle) + { + DragCursor = UserGetCurIconObject(CursorHandle); + } + else + { + iconic = FALSE; + } + } + } +#else if ( iconic ) /* create a cursor for dragging */ { - hDragCursor = pwnd->pcls->hIcon;; + hDragCursor = pwnd->pcls->hIcon; if ( !hDragCursor ) hDragCursor = (HCURSOR)co_IntSendMessage( UserHMGetHandle(pwnd), WM_QUERYDRAGICON, 0, 0 ); if ( !hDragCursor ) iconic = FALSE; } +#endif /* repaint the window before moving it around */ co_UserRedrawWindow( pwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN); @@ -558,14 +584,17 @@ DefWndDoSizeMove(PWND pwnd, WORD wParam) if ( !moved ) { moved = TRUE; - - if ( iconic ) /* ok, no system popup tracking */ - { - hOldCursor = IntSetCursor(hDragCursor); - UserShowCursor( TRUE ); - } - else if(!DragFullWindows) - UserDrawMovingFrame( hdc, &sizingRect, thickframe ); + if ( iconic ) /* ok, no system popup tracking */ + { +#ifdef NEW_CURSORICON + OldCursor = UserSetCursor(DragCursor, FALSE); +#else + hOldCursor = IntSetCursor(hDragCursor); +#endif + UserShowCursor( TRUE ); + } + else if(!DragFullWindows) + UserDrawMovingFrame( hdc, &sizingRect, thickframe ); } if (msg.message == WM_KEYDOWN) UserSetCursorPos(pt.x, pt.y, 0, 0, FALSE); @@ -644,10 +673,18 @@ DefWndDoSizeMove(PWND pwnd, WORD wParam) { if ( moved ) /* restore cursors, show icon title later on */ { - UserShowCursor( FALSE ); - IntSetCursor( hOldCursor ); + UserShowCursor( FALSE ); +#ifdef NEW_CURSORICON + UserSetCursor(OldCursor, FALSE); +#else + IntSetCursor( hOldCursor ); +#endif } +#ifdef NEW_CURSORICON + UserDereferenceObject(DragCursor); +#else IntDestroyCursor( hDragCursor, FALSE ); +#endif } else if ( moved && !DragFullWindows ) UserDrawMovingFrame( hdc, &sizingRect, thickframe ); @@ -990,6 +1027,19 @@ IntDefWindowProc( hDC = IntBeginPaint(Wnd, &Ps); if (hDC) { +#ifdef NEW_CURSORICON + if (((Wnd->style & WS_MINIMIZE) != 0) && (Wnd->pcls->spicn)) + { + RECT ClientRect; + INT x, y; + + ERR("Doing Paint and Client area is empty!\n"); + IntGetClientRect(Wnd, &ClientRect); + x = (ClientRect.right - ClientRect.left - UserGetSystemMetrics(SM_CXICON)) / 2; + y = (ClientRect.bottom - ClientRect.top - UserGetSystemMetrics(SM_CYICON)) / 2; + UserDrawIconEx(hDC, x, y, Wnd->pcls->spicn, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE); + } +#else HICON hIcon; if (((Wnd->style & WS_MINIMIZE) != 0) && (hIcon = Wnd->pcls->hIcon)) { @@ -1002,7 +1052,9 @@ IntDefWindowProc( x = (ClientRect.right - ClientRect.left - UserGetSystemMetrics(SM_CXICON)) / 2; y = (ClientRect.bottom - ClientRect.top - UserGetSystemMetrics(SM_CYICON)) / 2; UserDrawIconEx( hDC, x, y, pIcon, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE ); + UserDereferenceObject(pIcon) } +#endif IntEndPaint(Wnd, &Ps); } return (0); @@ -1096,23 +1148,38 @@ IntDefWindowProc( return lResult; } -HICON FASTCALL NC_IconForWindow( PWND pWnd ) +PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND pWnd ) { - HICON hIcon = 0; + PCURICON_OBJECT pIcon = NULL; + HICON hIcon; // First thing to do, init the Window Logo icons. if (!gpsi->hIconSmWindows) co_IntSetWndIcons(); - if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp); - if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp); - if (!hIcon) hIcon = pWnd->pcls->hIconSm; - if (!hIcon) hIcon = pWnd->pcls->hIcon; + //FIXME: Some callers use this function as if it returns a boolean saying "this window has an icon". + //FIXME: Hence we must return a pointer with no reference count. + //FIXME: This is bad and we should feel bad. - if (!hIcon && pWnd->style & DS_MODALFRAME) + hIcon = UserGetProp(pWnd, gpsi->atomIconSmProp); + if (!hIcon) hIcon = UserGetProp(pWnd, gpsi->atomIconProp); + if (!hIcon && pWnd->pcls->spicnSm) + return pWnd->pcls->spicnSm; + if (!hIcon && pWnd->pcls->spicn) + return pWnd->pcls->spicn; + + if (!hIcon && (pWnd->style & DS_MODALFRAME)) { if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small if (!hIcon) hIcon = gpsi->hIconWindows; // Reg size. } - return hIcon; + if (hIcon) + { + pIcon = UserGetCurIconObject(hIcon); + if (pIcon) + { + UserDereferenceObject(pIcon); + } + } + return pIcon; } DWORD FASTCALL diff --git a/reactos/win32ss/user/ntuser/main.c b/reactos/win32ss/user/ntuser/main.c index c668bbb27a3..bfc68de9d16 100644 --- a/reactos/win32ss/user/ntuser/main.c +++ b/reactos/win32ss/user/ntuser/main.c @@ -238,6 +238,11 @@ DestroyProcessInfo(PEPROCESS Process) ppiCurrent->hdeskStartup = NULL; } +#ifdef NEW_CURSORICON + /* Clean up the process icon cache */ + IntCleanupCurIconCache(ppiCurrent); +#endif + /* The process is dying */ PsSetProcessWin32Process(Process, NULL, ppiCurrent); ppiCurrent->peProcess = NULL; diff --git a/reactos/win32ss/user/ntuser/object.c b/reactos/win32ss/user/ntuser/object.c index 321d90fedc9..a598807bcb5 100644 --- a/reactos/win32ss/user/ntuser/object.c +++ b/reactos/win32ss/user/ntuser/object.c @@ -218,7 +218,11 @@ static const struct { NULL, NULL, NULL }, /* TYPE_FREE */ { AllocDeskThreadObject, co_UserDestroyWindow, FreeDeskThreadObject }, /* TYPE_WINDOW */ { AllocDeskProcObject, UserDestroyMenuObject, FreeDeskProcObject }, /* TYPE_MENU */ +#ifndef NEW_CURSORICON { AllocProcMarkObject, /*UserCursorCleanup*/NULL, FreeProcMarkObject }, /* TYPE_CURSOR */ +#else + { AllocProcMarkObject, IntDestroyCurIconObject, FreeProcMarkObject }, /* TYPE_CURSOR */ +#endif { AllocSysObject, /*UserSetWindowPosCleanup*/NULL, FreeSysObject }, /* TYPE_SETWINDOWPOS */ { AllocDeskThreadObject, IntRemoveHook, FreeDeskThreadObject }, /* TYPE_HOOK */ { AllocSysObject, /*UserClipDataCleanup*/NULL,FreeSysObject }, /* TYPE_CLIPDATA */ @@ -686,6 +690,7 @@ UserReferenceObjectByHandle(HANDLE handle, HANDLE_TYPE type) return object; } +#ifndef NEW_CURSORICON VOID FASTCALL UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner) @@ -720,6 +725,7 @@ UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner) ppi->UserHandleCount++; IntReferenceProcessInfo(ppi); } +#endif BOOLEAN UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner) @@ -740,6 +746,7 @@ UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner) if (Entry->flags & HANDLEENTRY_INDESTROY) continue; +#ifndef NEW_CURSORICON /* Spcial case for cursors until cursoricon_new is there */ if (Entry->type == TYPE_CURSOR) { @@ -750,6 +757,7 @@ UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner) } continue; } +#endif /* Call destructor */ if (!ObjectCallbacks[Entry->type].ObjectDestroy(Entry->ptr)) diff --git a/reactos/win32ss/user/ntuser/object.h b/reactos/win32ss/user/ntuser/object.h index e90d66cc983..2270fc75f9f 100644 --- a/reactos/win32ss/user/ntuser/object.h +++ b/reactos/win32ss/user/ntuser/object.h @@ -17,7 +17,9 @@ PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE, HANDLE, HANDLE_TYPE); BOOL FASTCALL UserCreateHandleTable(VOID); BOOL FASTCALL UserObjectInDestroy(HANDLE); void DbgUserDumpHandleTable(); +#ifndef NEW_CURSORICON VOID FASTCALL UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner); +#endif PVOID FASTCALL ValidateHandle(HANDLE handle, HANDLE_TYPE type); BOOLEAN UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner); diff --git a/reactos/win32ss/user/ntuser/painting.c b/reactos/win32ss/user/ntuser/painting.c index 362bddaa7cf..c6335fb800b 100644 --- a/reactos/win32ss/user/ntuser/painting.c +++ b/reactos/win32ss/user/ntuser/painting.c @@ -2122,13 +2122,17 @@ BOOL UserDrawCaption( { PCURICON_OBJECT pIcon = NULL; - if (!hIcon && pWnd) - { - hIcon = NC_IconForWindow( pWnd ); - } - if (hIcon) - pIcon = UserGetCurIconObject(hIcon); + { + pIcon = UserGetCurIconObject(hIcon); + } + else if (pWnd) + { + pIcon = NC_IconForWindow(pWnd); + // FIXME: NC_IconForWindow should reference it for us */ + if (pIcon) + UserReferenceObject(pIcon); + } if (pIcon) { diff --git a/reactos/win32ss/user/ntuser/painting.h b/reactos/win32ss/user/ntuser/painting.h index 76cf6e07cfd..da08b53d423 100644 --- a/reactos/win32ss/user/ntuser/painting.h +++ b/reactos/win32ss/user/ntuser/painting.h @@ -10,4 +10,4 @@ BOOL FASTCALL IntValidateParent(PWND Child, PREGION ValidateRgn, BOOL Recurse); BOOL FASTCALL IntIsWindowDirty(PWND); BOOL FASTCALL IntEndPaint(PWND,PPAINTSTRUCT); HDC FASTCALL IntBeginPaint(PWND,PPAINTSTRUCT); -HICON FASTCALL NC_IconForWindow( PWND ); +PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND ); diff --git a/reactos/win32ss/user/ntuser/windc.c b/reactos/win32ss/user/ntuser/windc.c index afee0f38f5d..316fe334f4d 100644 --- a/reactos/win32ss/user/ntuser/windc.c +++ b/reactos/win32ss/user/ntuser/windc.c @@ -403,8 +403,7 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags) Flags |= DCX_CLIPCHILDREN; } /* If minized with icon in the set, we are forced to be cheap! */ - if (Wnd->style & WS_MINIMIZE && - Wnd->pcls->hIcon) + if (Wnd->style & WS_MINIMIZE && Wnd->pcls->spicn) { Flags |= DCX_CACHE; } diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 9505717328e..9d76efe9b26 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -1674,7 +1674,24 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, } pWnd->head.pti->cWindows++; - +#ifdef NEW_CURSORICON + if (Class->spicn && !Class->spicnSm) + { + HICON IconSmHandle = co_IntCopyImage( + UserHMGetHandle(Class->spicn), + IMAGE_ICON, + UserGetSystemMetrics( SM_CXSMICON ), + UserGetSystemMetrics( SM_CYSMICON ), + 0); + if (IconSmHandle) + { + Class->spicnSm = UserGetCurIconObject(IconSmHandle); + /* We can delete the handle, only the pointer is of interest */ + NtUserDestroyCursor(IconSmHandle, FALSE); + Class->CSF_flags |= CSF_CACHEDSMICON; + } + } +#else if (Class->hIcon && !Class->hIconSm) { Class->hIconSmIntern = co_IntCopyImage( Class->hIcon, IMAGE_ICON, @@ -1683,6 +1700,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs, TRACE("IntCreateWindow hIconSmIntern %p\n",Class->hIconSmIntern); Class->CSF_flags |= CSF_CACHEDSMICON; } +#endif if (pWnd->pcls->CSF_flags & CSF_SERVERSIDEPROC) pWnd->state |= WNDS_SERVERSIDEWINDOWPROC; diff --git a/reactos/win32ss/user/user32/windows/class.c b/reactos/win32ss/user/user32/windows/class.c index 7ca74932532..fbfa9a6382e 100644 --- a/reactos/win32ss/user/user32/windows/class.c +++ b/reactos/win32ss/user/user32/windows/class.c @@ -712,7 +712,19 @@ IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex) case GCW_ATOM: Ret = (ULONG_PTR)Class->atomClassName; break; +#ifdef NEW_CURSORICON + case GCLP_HCURSOR: + Ret = Class->spcur ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spcur))->h : 0; + break; + case GCLP_HICON: + Ret = Class->spicn ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spicn))->h : 0; + break; + + case GCLP_HICONSM: + Ret = Class->spicnSm ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spicnSm))->h : 0; + break; +#else case GCLP_HCURSOR: /* FIXME - get handle from pointer to CURSOR object */ Ret = (ULONG_PTR)Class->hCursor; @@ -727,6 +739,7 @@ IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex) /* FIXME - get handle from pointer to ICON object */ Ret = (ULONG_PTR)(Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern); break; +#endif case GCLP_WNDPROC: Ret = IntGetClsWndProc(Wnd, Class, TRUE); @@ -790,6 +803,19 @@ IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex) Ret = (ULONG_PTR)Class->atomClassName; break; +#ifdef NEW_CURSORICON + case GCLP_HCURSOR: + Ret = Class->spcur ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spcur))->h : 0; + break; + + case GCLP_HICON: + Ret = Class->spicn ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spicn))->h : 0; + break; + + case GCLP_HICONSM: + Ret = Class->spicnSm ? (ULONG_PTR)((PPROCMARKHEAD)DesktopPtrToUser(Class->spicnSm))->h : 0; + break; +#else case GCLP_HCURSOR: /* FIXME - get handle from pointer to CURSOR object */ Ret = (ULONG_PTR)Class->hCursor; @@ -804,6 +830,7 @@ IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex) /* FIXME - get handle from pointer to ICON object */ Ret = (ULONG_PTR)(Class->hIconSm ? Class->hIconSm : Class->hIconSmIntern); break; +#endif case GCLP_WNDPROC: Ret = IntGetClsWndProc(Wnd, Class, FALSE);