2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Layered window support
5 * FILE: win32ss/user/ntuser/layered.c
10 DBG_DEFAULT_CHANNEL(UserMisc
);
13 typedef struct _LRD_PROP
20 } LRD_PROP
, *PLRD_PROP
;
23 GetLayeredStatus(PWND pWnd
)
25 PLRD_PROP pLrdProp
= UserGetProp(pWnd
, AtomLayer
, TRUE
);
28 return pLrdProp
->is_Layered
;
34 SetLayeredStatus(PWND pWnd
, BYTE set
)
36 PLRD_PROP pLrdProp
= UserGetProp(pWnd
, AtomLayer
, TRUE
);
39 pLrdProp
->is_Layered
= set
;
46 IntSetLayeredWindowAttributes(PWND pWnd
,
54 if (!(pWnd
->ExStyle
& WS_EX_LAYERED
) )
56 ERR("Not a Layered Window!\n");
60 pLrdProp
= UserGetProp(pWnd
, AtomLayer
, TRUE
);
64 pLrdProp
= ExAllocatePoolWithTag(PagedPool
, sizeof(LRD_PROP
), USERTAG_REDIRECT
);
67 ERR("failed to allocate LRD_PROP\n");
70 RtlZeroMemory(pLrdProp
, sizeof(LRD_PROP
));
71 UserSetProp(pWnd
, AtomLayer
, (HANDLE
)pLrdProp
, TRUE
);
76 was_Layered
= pLrdProp
->is_Layered
;
78 pLrdProp
->Key
= crKey
;
80 if (dwFlags
& LWA_ALPHA
)
82 pLrdProp
->Alpha
= bAlpha
;
86 if (!pLrdProp
->is_Layered
) pLrdProp
->Alpha
= 0;
89 pLrdProp
->Flags
= dwFlags
;
91 pLrdProp
->is_Layered
= 1;
94 co_UserRedrawWindow(pWnd
, NULL
, NULL
, RDW_INVALIDATE
| RDW_ERASE
| RDW_FRAME
);
96 // FIXME: Now set some bits to the Window DC!!!!
101 IntUpdateLayeredWindowI( PWND pWnd
,
102 UPDATELAYEREDWINDOWINFO
*info
)
108 DWORD flags
= SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
;
110 Window
= pWnd
->rcWindow
;
111 Client
= pWnd
->rcClient
;
113 Parent
= pWnd
->spwndParent
;
114 if (pWnd
->style
& WS_CHILD
&& Parent
)
116 RECTL_vOffsetRect(&Window
, - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
117 RECTL_vOffsetRect(&Client
, - Parent
->rcClient
.left
, - Parent
->rcClient
.top
);
122 Offset
.cx
= info
->pptDst
->x
- Window
.left
;
123 Offset
.cy
= info
->pptDst
->y
- Window
.top
;
124 RECTL_vOffsetRect( &Client
, Offset
.cx
, Offset
.cy
);
125 RECTL_vOffsetRect( &Window
, Offset
.cx
, Offset
.cy
);
126 flags
&= ~SWP_NOMOVE
;
130 Offset
.cx
= info
->psize
->cx
- (Window
.right
- Window
.left
);
131 Offset
.cy
= info
->psize
->cy
- (Window
.bottom
- Window
.top
);
132 if (info
->psize
->cx
<= 0 || info
->psize
->cy
<= 0)
134 ERR("Update Layered Invalid Parameters\n");
135 EngSetLastError( ERROR_INVALID_PARAMETER
);
138 if ((info
->dwFlags
& ULW_EX_NORESIZE
) && (Offset
.cx
|| Offset
.cy
))
141 EngSetLastError( ERROR_INCORRECT_SIZE
);
144 Client
.right
+= Offset
.cx
;
145 Client
.bottom
+= Offset
.cy
;
146 Window
.right
+= Offset
.cx
;
147 Window
.bottom
+= Offset
.cy
;
148 flags
&= ~SWP_NOSIZE
;
155 BLENDFUNCTION blend
= { AC_SRC_OVER
, 0, 255, 0 };
156 COLORREF color_key
= (info
->dwFlags
& ULW_COLORKEY
) ? info
->crKey
: CLR_INVALID
;
157 HBITMAP hOldBitmap
, hOldBitmap1
, hbmSrc
, hbmDst
;
162 RECTL_vOffsetRect( &Rect
, -Window
.left
, -Window
.top
);
164 TRACE("H %d W %d\n",Rect
.bottom
- Rect
.top
,Rect
.right
- Rect
.left
);
166 if (!info
->hdcDst
) hdc
= UserGetDCEx(pWnd
, NULL
, DCX_USESTYLE
);
167 else hdc
= info
->hdcDst
;
169 hbmSrc
= NtGdiCreateCompatibleBitmap(info
->hdcSrc
, Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
);
170 hbmDst
= NtGdiCreateCompatibleBitmap(info
->hdcSrc
, Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
);
172 GreGetObject(hbmSrc
, sizeof(DIBSECTION
), &dibs
);
174 TRACE("Source Bitmap bc %d\n",dibs
.dsBmih
.biBitCount
);
176 hdcBuffer
= NtGdiCreateCompatibleDC(hdc
);
178 hOldBitmap
= (HBITMAP
)NtGdiSelectBitmap(hdcBuffer
, hbmSrc
);
179 hOldBitmap1
= (HBITMAP
)NtGdiSelectBitmap(hdc
, hbmDst
);
181 NtGdiStretchBlt( hdcBuffer
,
184 Rect
.right
- Rect
.left
,
185 Rect
.bottom
- Rect
.top
,
187 Rect
.left
+ (info
->pptSrc
? info
->pptSrc
->x
: 0),
188 Rect
.top
+ (info
->pptSrc
? info
->pptSrc
->y
: 0),
189 Rect
.right
- Rect
.left
,
190 Rect
.bottom
- Rect
.top
,
194 // Need to test this, Dirty before or after StretchBlt?
198 RECTL_bIntersectRect( &Rect
, &Rect
, info
->prcDirty
);
199 NtGdiPatBlt( hdc
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, BLACKNESS
);
202 if (info
->dwFlags
& ULW_ALPHA
)
204 blend
= *info
->pblend
;
205 TRACE("ULW_ALPHA bop %d Alpha %d aF %d\n", blend
.BlendOp
, blend
.SourceConstantAlpha
, blend
.AlphaFormat
);
208 ret
= NtGdiAlphaBlend( hdc
,
211 Rect
.right
- Rect
.left
,
212 Rect
.bottom
- Rect
.top
,
214 Rect
.left
+ (info
->pptSrc
? info
->pptSrc
->x
: 0),
215 Rect
.top
+ (info
->pptSrc
? info
->pptSrc
->y
: 0),
216 Rect
.right
- Rect
.left
,
217 Rect
.bottom
- Rect
.top
,
221 NtGdiSelectBitmap(hdc
, hOldBitmap1
);
222 NtGdiSelectBitmap(hdcBuffer
, hOldBitmap
);
223 if (hbmSrc
) GreDeleteObject(hbmSrc
);
224 if (hbmDst
) GreDeleteObject(hbmDst
);
225 if (hdcBuffer
) IntGdiDeleteDC(hdcBuffer
, FALSE
);
226 if (!info
->hdcDst
) UserReleaseDC(pWnd
, hdc
, FALSE
);
231 co_WinPosSetWindowPos(pWnd
, 0, Window
.left
, Window
.top
, Window
.right
- Window
.left
, Window
.bottom
- Window
.top
, flags
);
241 NtUserGetLayeredWindowAttributes(
251 TRACE("Enter NtUserGetLayeredWindowAttributes\n");
252 UserEnterExclusive();
254 if (!(pWnd
= UserGetWindowObject(hwnd
)) ||
255 !(pWnd
->ExStyle
& WS_EX_LAYERED
) )
257 ERR("Not a Layered Window!\n");
261 pLrdProp
= UserGetProp(pWnd
, AtomLayer
, TRUE
);
269 if (pLrdProp
->is_Layered
== 0)
278 ProbeForWrite(pcrKey
, sizeof(*pcrKey
), 1);
279 *pcrKey
= pLrdProp
->Key
;
283 ProbeForWrite(pbAlpha
, sizeof(*pbAlpha
), 1);
284 *pbAlpha
= pLrdProp
->Alpha
;
288 ProbeForWrite(pdwFlags
, sizeof(*pdwFlags
), 1);
289 *pdwFlags
= pLrdProp
->Flags
;
292 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
294 SetLastNtError(_SEH2_GetExceptionCode());
295 _SEH2_YIELD(goto Exit
);
302 TRACE("Leave NtUserGetLayeredWindowAttributes, ret=%i\n", Ret
);
311 NtUserSetLayeredWindowAttributes(HWND hwnd
,
319 TRACE("Enter NtUserSetLayeredWindowAttributes\n");
320 UserEnterExclusive();
322 if (!(pWnd
= UserGetWindowObject(hwnd
)) ||
323 !(pWnd
->ExStyle
& WS_EX_LAYERED
) )
325 ERR("Not a Layered Window!\n");
329 Ret
= IntSetLayeredWindowAttributes(pWnd
, crKey
, bAlpha
, dwFlags
);
331 TRACE("Leave NtUserSetLayeredWindowAttributes, ret=%i\n", Ret
);
341 NtUserUpdateLayeredWindow(
349 BLENDFUNCTION
*pblend
,
353 UPDATELAYEREDWINDOWINFO info
;
357 BLENDFUNCTION blend
= { AC_SRC_OVER
, 0, 255, 0 };
361 TRACE("Enter NtUserUpdateLayeredWindow\n");
362 UserEnterExclusive();
364 if (!(pWnd
= UserGetWindowObject(hwnd
)))
373 ProbeForRead(pptDst
, sizeof(POINT
), 1);
378 ProbeForRead(pptSrc
, sizeof(POINT
), 1);
381 ProbeForRead(psize
, sizeof(SIZE
), 1);
385 ProbeForRead(pblend
, sizeof(BLENDFUNCTION
), 1);
390 ProbeForRead(prcDirty
, sizeof(RECT
), 1);
394 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
396 EngSetLastError( ERROR_INVALID_PARAMETER
);
397 _SEH2_YIELD(goto Exit
);
401 if ( GetLayeredStatus(pWnd
) ||
402 dwFlags
& ~(ULW_COLORKEY
| ULW_ALPHA
| ULW_OPAQUE
| ULW_EX_NORESIZE
) ||
403 !(pWnd
->ExStyle
& WS_EX_LAYERED
) )
405 ERR("Layered Window Invalid Parameters\n");
406 EngSetLastError( ERROR_INVALID_PARAMETER
);
410 info
.cbSize
= sizeof(info
);
411 info
.hdcDst
= hdcDst
;
412 info
.pptDst
= pptDst
? &Dst
: NULL
;
414 info
.hdcSrc
= hdcSrc
;
415 info
.pptSrc
= pptSrc
? &Src
: NULL
;
417 info
.pblend
= &blend
;
418 info
.dwFlags
= dwFlags
;
419 info
.prcDirty
= prcDirty
? &Dirty
: NULL
;
420 Ret
= IntUpdateLayeredWindowI( pWnd
, &info
);
422 TRACE("Leave NtUserUpdateLayeredWindow, ret=%i\n", Ret
);