2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/ntuser/windc.c
5 * PURPOSE: Keyboard layout management
6 * COPYRIGHT: Copyright 2007 ReactOS
10 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 /* NOTE - I think we should store this per window station (including gdi objects) */
21 static PDCE FirstDce
= NULL
;
22 //static INT DCECount = 0; // Count of DCE in system.
24 #define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
25 DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP)
27 /* FUNCTIONS *****************************************************************/
30 // This should be moved to dc.c or dcutil.c.
33 DceCreateDisplayDC(VOID
)
36 UNICODE_STRING DriverName
;
37 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
38 hDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, FALSE
);
40 // If NULL, first time through! Build the default window dc!
42 if (hDC
&& !defaultDCstate
) // Ultra HAX! Dedicated to GvG!
43 { // This is a cheesy way to do this.
44 PDC dc
= DC_LockDc ( hDC
);
45 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
46 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
47 IntGdiCopyToSaveState(dc
, defaultDCstate
);
55 DceGetVisRgn(PWINDOW_OBJECT Window
, ULONG Flags
, HWND hWndChild
, ULONG CFlags
)
59 VisRgn
= VIS_ComputeVisibleRegion( Window
,
60 0 == (Flags
& DCX_WINDOW
),
61 0 != (Flags
& DCX_CLIPCHILDREN
),
62 0 != (Flags
& DCX_CLIPSIBLINGS
));
65 VisRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
72 DceAllocDCE(PWINDOW_OBJECT Window OPTIONAL
, DCE_TYPE Type
)
77 if (Window
) Wnd
= Window
->Wnd
;
79 pDce
= ExAllocatePoolWithTag(PagedPool
, sizeof(DCE
), TAG_PDCE
);
83 pDce
->hDC
= DceCreateDisplayDC();
86 ExFreePoolWithTag(pDce
, TAG_PDCE
);
90 pDce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
91 pDce
->hClipRgn
= NULL
;
92 pDce
->pProcess
= NULL
;
94 KeEnterCriticalRegion();
98 InitializeListHead(&FirstDce
->List
);
101 InsertTailList(&FirstDce
->List
, &pDce
->List
);
102 KeLeaveCriticalRegion();
104 DCU_SetDcUndeletable(pDce
->hDC
);
106 if (Type
== DCE_WINDOW_DC
|| Type
== DCE_CLASS_DC
) //Window DCE have ownership.
107 { // Process should already own it.
108 pDce
->pProcess
= PsGetCurrentProcess();
112 DPRINT("FREE DCATTR!!!! NOT DCE_WINDOW_DC!!!!! hDC-> %x\n", pDce
->hDC
);
113 IntGdiSetDCOwnerEx( pDce
->hDC
, GDI_OBJ_HMGR_NONE
, FALSE
);
116 if (Type
== DCE_CACHE_DC
)
118 pDce
->DCXFlags
= DCX_CACHE
| DCX_DCEEMPTY
;
122 pDce
->DCXFlags
= DCX_DCEBUSY
;
125 if (Type
== DCE_WINDOW_DC
)
127 if (Wnd
->Style
& WS_CLIPCHILDREN
) pDce
->DCXFlags
|= DCX_CLIPCHILDREN
;
128 if (Wnd
->Style
& WS_CLIPSIBLINGS
) pDce
->DCXFlags
|= DCX_CLIPSIBLINGS
;
136 DceSetDrawable(PWINDOW_OBJECT Window OPTIONAL
, HDC hDC
, ULONG Flags
,
140 DC
*dc
= DC_LockDc(hDC
);
152 if (Flags
& DCX_WINDOW
)
154 dc
->ptlDCOrig
.x
= Wnd
->WindowRect
.left
;
155 dc
->ptlDCOrig
.y
= Wnd
->WindowRect
.top
;
159 dc
->ptlDCOrig
.x
= Wnd
->ClientRect
.left
;
160 dc
->ptlDCOrig
.y
= Wnd
->ClientRect
.top
;
168 DceDeleteClipRgn(DCE
* Dce
)
170 Dce
->DCXFlags
&= ~(DCX_EXCLUDERGN
| DCX_INTERSECTRGN
);
172 if (Dce
->DCXFlags
& DCX_KEEPCLIPRGN
)
174 Dce
->DCXFlags
&= ~DCX_KEEPCLIPRGN
;
176 else if (Dce
->hClipRgn
!= NULL
)
178 NtGdiDeleteObject(Dce
->hClipRgn
);
181 Dce
->hClipRgn
= NULL
;
183 /* make it dirty so that the vis rgn gets recomputed next time */
184 Dce
->DCXFlags
|= DCX_DCEDIRTY
;
188 DceReleaseDC(DCE
* dce
, BOOL EndPaint
)
190 if (DCX_DCEBUSY
!= (dce
->DCXFlags
& (DCX_DCEEMPTY
| DCX_DCEBUSY
)))
195 /* restore previous visible region */
197 if ((dce
->DCXFlags
& (DCX_INTERSECTRGN
| DCX_EXCLUDERGN
)) &&
198 ((dce
->DCXFlags
& DCX_CACHE
) || EndPaint
))
200 DceDeleteClipRgn(dce
);
203 if (dce
->DCXFlags
& DCX_CACHE
)
205 if (!(dce
->DCXFlags
& DCX_NORESETATTRS
))
207 /* make the DC clean so that SetDCState doesn't try to update the vis rgn */
208 IntGdiSetHookFlags(dce
->hDC
, DCHF_VALIDATEVISRGN
);
211 if (!IntGdiCleanDC(dce
->hDC
)) return 0;
213 if (dce
->DCXFlags
& DCX_DCEDIRTY
)
215 /* don't keep around invalidated entries
216 * because SetDCState() disables hVisRgn updates
217 * by removing dirty bit. */
218 dce
->hwndCurrent
= 0;
219 dce
->DCXFlags
&= DCX_CACHE
;
220 dce
->DCXFlags
|= DCX_DCEEMPTY
;
223 dce
->DCXFlags
&= ~DCX_DCEBUSY
;
224 DPRINT("Exit!!!!! DCX_CACHE!!!!!! hDC-> %x \n", dce
->hDC
);
225 if (!IntGdiSetDCOwnerEx( dce
->hDC
, GDI_OBJ_HMGR_NONE
, FALSE
))
227 dce
->pProcess
= NULL
; // Reset ownership.
229 return 1; // Released!
233 DceUpdateVisRgn(DCE
*Dce
, PWINDOW_OBJECT Window
, ULONG Flags
)
235 HANDLE hRgnVisible
= NULL
;
237 PWINDOW_OBJECT DesktopWindow
;
239 if (Flags
& DCX_PARENTCLIP
)
241 PWINDOW_OBJECT Parent
;
244 Parent
= Window
->Parent
;
251 ParentWnd
= Parent
->Wnd
;
253 if (ParentWnd
->Style
& WS_CLIPSIBLINGS
)
255 DcxFlags
= DCX_CLIPSIBLINGS
|
256 (Flags
& ~(DCX_CLIPCHILDREN
| DCX_WINDOW
));
260 DcxFlags
= Flags
& ~(DCX_CLIPSIBLINGS
| DCX_CLIPCHILDREN
| DCX_WINDOW
);
262 hRgnVisible
= DceGetVisRgn(Parent
, DcxFlags
, Window
->hSelf
, Flags
);
264 else if (Window
== NULL
)
266 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
267 if (NULL
!= DesktopWindow
)
269 hRgnVisible
= UnsafeIntCreateRectRgnIndirect(&DesktopWindow
->Wnd
->WindowRect
);
278 hRgnVisible
= DceGetVisRgn(Window
, Flags
, 0, 0);
282 if (Flags
& DCX_INTERSECTRGN
)
284 if(Dce
->hClipRgn
!= NULL
)
286 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hClipRgn
, RGN_AND
);
290 if(hRgnVisible
!= NULL
)
292 NtGdiDeleteObject(hRgnVisible
);
294 hRgnVisible
= NtGdiCreateRectRgn(0, 0, 0, 0);
298 if (Flags
& DCX_EXCLUDERGN
&& Dce
->hClipRgn
!= NULL
)
300 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hClipRgn
, RGN_DIFF
);
303 Dce
->DCXFlags
&= ~DCX_DCEDIRTY
;
304 GdiSelectVisRgn(Dce
->hDC
, hRgnVisible
);
308 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
311 if (hRgnVisible
!= NULL
)
313 NtGdiDeleteObject(hRgnVisible
);
318 UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
320 PWINDOW_OBJECT Parent
;
323 BOOL UpdateVisRgn
= TRUE
;
324 BOOL UpdateClipOrigin
= FALSE
;
330 Flags
&= ~DCX_USESTYLE
;
336 if (Flags
& (DCX_WINDOW
| DCX_PARENTCLIP
)) Flags
|= DCX_CACHE
;
338 // When GetDC is called with hWnd nz, DCX_CACHE & _WINDOW are clear w _USESTYLE set.
339 if (Flags
& DCX_USESTYLE
)
341 Flags
&= ~(DCX_CLIPCHILDREN
| DCX_CLIPSIBLINGS
| DCX_PARENTCLIP
);
342 if (!(Flags
& DCX_WINDOW
)) // not window rectangle
344 if (Wnd
->Class
->Style
& CS_PARENTDC
)
346 Flags
|= DCX_PARENTCLIP
;
349 if (!(Flags
& DCX_CACHE
) && // Not on the cheap wine list.
350 !(Wnd
->Class
->Style
& CS_OWNDC
) )
352 if (!(Wnd
->Class
->Style
& CS_CLASSDC
))
353 // The window is not POWNED or has any CLASS, so we are looking for cheap wine.
357 if (Wnd
->Class
->Dce
) hDC
= ((PDCE
)Wnd
->Class
->Dce
)->hDC
;
358 DPRINT("We have CLASS!!\n");
361 /* else // For Testing!
363 DPRINT1("We have POWNER!!\n");
364 if (Window->Dce) DPRINT1("We have POWNER with DCE!!\n");
367 if (Wnd
->Style
& WS_CLIPSIBLINGS
)
369 Flags
|= DCX_CLIPSIBLINGS
;
372 if (Wnd
->Style
& WS_CLIPCHILDREN
&&
373 !(Wnd
->Style
& WS_MINIMIZE
))
375 Flags
|= DCX_CLIPCHILDREN
;
380 if (Wnd
->Style
& WS_CLIPSIBLINGS
) Flags
|= DCX_CLIPSIBLINGS
;
385 if (Flags
& DCX_WINDOW
) Flags
&= ~DCX_CLIPCHILDREN
;
387 if (Flags
& DCX_NOCLIPCHILDREN
)
390 Flags
&= ~(DCX_PARENTCLIP
| DCX_CLIPCHILDREN
);
393 Parent
= (Window
? Window
->Parent
: NULL
);
395 if (NULL
== Window
|| !(Wnd
->Style
& WS_CHILD
) || NULL
== Parent
)
397 Flags
&= ~DCX_PARENTCLIP
;
398 Flags
|= DCX_CLIPSIBLINGS
;
401 /* it seems parent clip is ignored when clipping siblings or children */
402 if (Flags
& (DCX_CLIPSIBLINGS
| DCX_CLIPCHILDREN
)) Flags
&= ~DCX_PARENTCLIP
;
404 if (Flags
& DCX_PARENTCLIP
)
406 if ((Wnd
->Style
& WS_VISIBLE
) &&
407 (Parent
->Wnd
->Style
& WS_VISIBLE
))
409 Flags
&= ~DCX_CLIPCHILDREN
;
410 if (Parent
->Wnd
->Style
& WS_CLIPSIBLINGS
)
412 Flags
|= DCX_CLIPSIBLINGS
;
417 // Window nz, check to see if we still own this or it is just cheap wine tonight.
418 if (!(Flags
& DCX_CACHE
))
420 if ( Wnd
->ti
!= GetW32ThreadInfo())
421 Flags
|= DCX_CACHE
; // Ah~ Not Powned! Forced to be cheap~
424 DcxFlags
= Flags
& DCX_CACHECOMPAREMASK
;
426 if (Flags
& DCX_CACHE
)
427 { // Scan the cheap wine list for our match.
428 DCE
* DceEmpty
= NULL
;
429 DCE
* DceUnused
= NULL
;
430 KeEnterCriticalRegion();
434 // The reason for this you may ask?
435 // Well, it seems ReactOS calls GetDC with out first creating a desktop DC window!
436 // Need to test for null here. Not sure if this is a bug or a feature.
437 // First time use hax, need to use DceAllocDCE during window display init.
440 // The way I understand this, you can have more than one DC per window.
441 // Only one Owned if one was requested and saved and one Cached.
443 if ((Dce
->DCXFlags
& (DCX_CACHE
| DCX_DCEBUSY
)) == DCX_CACHE
)
446 if (Dce
->DCXFlags
& DCX_DCEEMPTY
)
450 else if (Dce
->hwndCurrent
== (Window
? Window
->hSelf
: NULL
) &&
451 ((Dce
->DCXFlags
& DCX_CACHECOMPAREMASK
) == DcxFlags
))
454 UpdateVisRgn
= FALSE
;
456 UpdateClipOrigin
= TRUE
;
460 Dce
= (PDCE
)Dce
->List
.Flink
;
461 } while (Dce
!= FirstDce
);
462 KeLeaveCriticalRegion();
464 Dce
= (DceEmpty
== NULL
) ? DceUnused
: DceEmpty
;
468 Dce
= DceAllocDCE(NULL
, DCE_CACHE_DC
);
470 if (!Dce
) return NULL
;
472 Dce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
474 else // If we are here, we are POWNED or having CLASS.
476 KeEnterCriticalRegion();
479 { // Check for Window handle than HDC match for CLASS.
480 if ((Dce
->hwndCurrent
== Window
->hSelf
) || (Dce
->hDC
== hDC
)) break;
481 Dce
= (PDCE
)Dce
->List
.Flink
;
482 } while (Dce
!= FirstDce
);
483 KeLeaveCriticalRegion();
485 DPRINT("DCX:Flags -> %x:%x\n",Dce
->DCXFlags
& DCX_CACHE
, Flags
& DCX_CACHE
);
487 if (Dce
->hwndCurrent
== Window
->hSelf
)
489 DPRINT("Owned DCE!\n");
490 UpdateVisRgn
= FALSE
; /* updated automatically, via DCHook() */
494 DPRINT("Owned/Class DCE\n");
495 /* we should free dce->clip_rgn here, but Windows apparently doesn't */
496 Dce
->DCXFlags
&= ~(DCX_EXCLUDERGN
| DCX_INTERSECTRGN
);
497 Dce
->hClipRgn
= NULL
;
505 // First time use hax, need to use DceAllocDCE during window display init.
511 if (!GDIOBJ_ValidateHandle(Dce
->hDC
, GDI_OBJECT_TYPE_DC
))
513 DPRINT1("FIXME: Got DCE with invalid hDC! 0x%x\n", Dce
->hDC
);
514 Dce
->hDC
= DceCreateDisplayDC();
515 /* FIXME: Handle error */
518 if (!(Flags
& (DCX_EXCLUDERGN
| DCX_INTERSECTRGN
)) && ClipRegion
)
520 if (!(Flags
& DCX_KEEPCLIPRGN
))
521 NtGdiDeleteObject(ClipRegion
);
526 if (NULL
!= Dce
->hClipRgn
)
528 DceDeleteClipRgn(Dce
);
532 Dce
->DCXFlags
= Flags
| DCX_DCEBUSY
;
534 if (0 != (Flags
& DCX_INTERSECTUPDATE
) && NULL
== ClipRegion
)
536 Flags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
537 Dce
->DCXFlags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
538 ClipRegion
= Window
->UpdateRegion
;
541 if (ClipRegion
== (HRGN
) 1)
543 if (!(Flags
& DCX_WINDOW
))
545 Dce
->hClipRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->Wnd
->ClientRect
);
549 Dce
->hClipRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->Wnd
->WindowRect
);
551 Dce
->DCXFlags
&= ~DCX_KEEPCLIPRGN
;
553 else if (ClipRegion
!= NULL
)
555 Dce
->hClipRgn
= ClipRegion
;
558 DceSetDrawable(Window
, Dce
->hDC
, Flags
, UpdateClipOrigin
);
562 DceUpdateVisRgn(Dce
, Window
, Flags
);
565 if (Dce
->DCXFlags
& DCX_CACHE
)
567 DPRINT("ENTER!!!!!! DCX_CACHE!!!!!! hDC-> %x\n", Dce
->hDC
);
568 // Need to set ownership so Sync dcattr will work.
569 IntGdiSetDCOwnerEx( Dce
->hDC
, GDI_OBJ_HMGR_POWNED
, FALSE
);
570 Dce
->pProcess
= PsGetCurrentProcess(); // Set the temp owning process
575 /***********************************************************************
579 DceFreeDCE(PDCE pdce
, BOOLEAN Force
)
584 if (NULL
== pdce
) return NULL
;
586 ret
= (PDCE
) pdce
->List
.Flink
;
589 SetDCHook(pdce
->hDC
, NULL
, 0L);
592 if (Force
&& !GDIOBJ_OwnedByCurrentProcess(pdce
->hDC
))
594 DPRINT("Change ownership for DCE! -> %x\n" , pdce
);
595 // Note: Windows sets W32PF_OWNDCCLEANUP and moves on.
596 if (!IsObjectDead((HGDIOBJ
) pdce
->hDC
))
598 DC_SetOwnership( pdce
->hDC
, PsGetCurrentProcess());
602 DPRINT1("Attempted to change ownership of an DCEhDC 0x%x currently being destroyed!!!\n",pdce
->hDC
);
607 if (!Hit
) IntGdiDeleteDC(pdce
->hDC
, TRUE
);
609 if (pdce
->hClipRgn
&& ! (pdce
->DCXFlags
& DCX_KEEPCLIPRGN
))
611 NtGdiDeleteObject(pdce
->hClipRgn
);
614 RemoveEntryList(&pdce
->List
);
616 if (IsListEmpty(&pdce
->List
))
618 DPRINT1("List is Empty! DCE! -> %x\n" , pdce
);
623 ExFreePoolWithTag(pdce
, TAG_PDCE
);
629 /***********************************************************************
632 * Remove owned DCE and reset unreleased cache DCEs.
635 DceFreeWindowDCE(PWINDOW_OBJECT Window
)
640 KeEnterCriticalRegion();
644 if (pDCE
->hwndCurrent
== Window
->hSelf
)
646 if (!(pDCE
->DCXFlags
& DCX_CACHE
)) /* owned or Class DCE*/
648 if (Window
->Wnd
->Class
->Style
& CS_CLASSDC
||
649 Window
->Wnd
->Style
& CS_CLASSDC
) /* Test Class first */
651 if (pDCE
->DCXFlags
& (DCX_INTERSECTRGN
| DCX_EXCLUDERGN
)) /* Class DCE*/
652 DceDeleteClipRgn(pDCE
);
653 // Update and reset Vis Rgn and clear the dirty bit.
654 // Should release VisRgn than reset it to default.
655 DceUpdateVisRgn(pDCE
, Window
, pDCE
->DCXFlags
);
656 pDCE
->DCXFlags
= DCX_DCEEMPTY
;
657 pDCE
->hwndCurrent
= 0;
659 else if (Window
->Wnd
->Class
->Style
& CS_OWNDC
||
660 Window
->Wnd
->Style
& CS_OWNDC
) /* owned DCE*/
662 pDCE
= DceFreeDCE(pDCE
, FALSE
);
674 if (pDCE
->DCXFlags
& DCX_DCEBUSY
) /* shared cache DCE */
676 /* FIXME: AFAICS we are doing the right thing here so
677 * this should be a DPRINT. But this is best left as an ERR
678 * because the 'application error' is likely to come from
679 * another part of Wine (i.e. it's our fault after all).
680 * We should change this to DPRINT when ReactOS is more stable
683 DPRINT1("[%p] GetDC() without ReleaseDC()!\n", Window
->hSelf
);
684 DceReleaseDC(pDCE
, FALSE
);
686 pDCE
->DCXFlags
|= DCX_DCEEMPTY
;
687 pDCE
->hwndCurrent
= 0;
690 pDCE
= (PDCE
) pDCE
->List
.Flink
;
691 } while (pDCE
!= FirstDce
);
692 KeLeaveCriticalRegion();
696 DceFreeClassDCE(HDC hDC
)
698 PDCE pDCE
= FirstDce
;
699 KeEnterCriticalRegion();
703 if (pDCE
->hDC
== hDC
)
705 pDCE
= DceFreeDCE(pDCE
, FALSE
);
709 pDCE
= (PDCE
)pDCE
->List
.Flink
;
710 } while (pDCE
!= FirstDce
);
711 KeLeaveCriticalRegion();
717 PDCE pDCE
= FirstDce
;
718 KeEnterCriticalRegion();
722 pDCE
= DceFreeDCE(pDCE
, TRUE
);
724 } while (pDCE
!= FirstDce
);
725 KeLeaveCriticalRegion();
730 DceResetActiveDCEs(PWINDOW_OBJECT Window
)
734 PWINDOW_OBJECT CurrentWindow
;
743 if(!pDCE
) return; // Another null test!
747 if (0 == (pDCE
->DCXFlags
& DCX_DCEEMPTY
))
749 if (Window
->hSelf
== pDCE
->hwndCurrent
)
751 CurrentWindow
= Window
;
755 CurrentWindow
= UserGetWindowObject(pDCE
->hwndCurrent
);
756 if (NULL
== CurrentWindow
)
758 pDCE
= (PDCE
) pDCE
->List
.Flink
;
763 if (!GDIOBJ_ValidateHandle(pDCE
->hDC
, GDI_OBJECT_TYPE_DC
) ||
764 (dc
= DC_LockDc(pDCE
->hDC
)) == NULL
)
766 pDCE
= (PDCE
) pDCE
->List
.Flink
;
769 if (Window
== CurrentWindow
|| IntIsChildWindow(Window
, CurrentWindow
))
771 if (pDCE
->DCXFlags
& DCX_WINDOW
)
773 DeltaX
= CurrentWindow
->Wnd
->WindowRect
.left
- dc
->ptlDCOrig
.x
;
774 DeltaY
= CurrentWindow
->Wnd
->WindowRect
.top
- dc
->ptlDCOrig
.y
;
775 dc
->ptlDCOrig
.x
= CurrentWindow
->Wnd
->WindowRect
.left
;
776 dc
->ptlDCOrig
.y
= CurrentWindow
->Wnd
->WindowRect
.top
;
780 DeltaX
= CurrentWindow
->Wnd
->ClientRect
.left
- dc
->ptlDCOrig
.x
;
781 DeltaY
= CurrentWindow
->Wnd
->ClientRect
.top
- dc
->ptlDCOrig
.y
;
782 dc
->ptlDCOrig
.x
= CurrentWindow
->Wnd
->ClientRect
.left
;
783 dc
->ptlDCOrig
.y
= CurrentWindow
->Wnd
->ClientRect
.top
;
785 if (NULL
!= dc
->w
.hClipRgn
)
787 int FASTCALL
CLIPPING_UpdateGCRegion(DC
* Dc
);
788 NtGdiOffsetRgn(dc
->w
.hClipRgn
, DeltaX
, DeltaY
);
789 CLIPPING_UpdateGCRegion(dc
);
791 if (NULL
!= pDCE
->hClipRgn
)
793 NtGdiOffsetRgn(pDCE
->hClipRgn
, DeltaX
, DeltaY
);
798 DceUpdateVisRgn(pDCE
, CurrentWindow
, pDCE
->DCXFlags
);
800 if (Window
->hSelf
!= pDCE
->hwndCurrent
)
802 // IntEngWindowChanged(CurrentWindow, WOC_RGN_CLIENT);
803 // UserDerefObject(CurrentWindow);
806 pDCE
=(PDCE
) pDCE
->List
.Flink
;
807 } while (pDCE
!= FirstDce
);
811 IntWindowFromDC(HDC hDc
)
815 KeEnterCriticalRegion();
821 Ret
= Dce
->hwndCurrent
;
824 Dce
= (PDCE
)Dce
->List
.Flink
;
825 } while (Dce
!= FirstDce
);
826 KeLeaveCriticalRegion();
831 UserReleaseDC(PWINDOW_OBJECT Window
, HDC hDc
, BOOL EndPaint
)
837 DPRINT("%p %p\n", Window
, hDc
);
839 KeEnterCriticalRegion();
849 dce
= (PDCE
) dce
->List
.Flink
;
851 while (dce
!= FirstDce
);
852 KeLeaveCriticalRegion();
854 if ( Hit
&& (dce
->DCXFlags
& DCX_DCEBUSY
))
856 nRet
= DceReleaseDC(dce
, EndPaint
);
863 UserGetWindowDC(PWINDOW_OBJECT Wnd
)
865 return UserGetDCEx(Wnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
869 NtUserGetDCEx(HWND hWnd OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
871 PWINDOW_OBJECT Wnd
=NULL
;
874 DPRINT("Enter NtUserGetDCEx\n");
875 UserEnterExclusive();
877 if (hWnd
&& !(Wnd
= UserGetWindowObject(hWnd
)))
881 RETURN( UserGetDCEx(Wnd
, ClipRegion
, Flags
));
884 DPRINT("Leave NtUserGetDCEx, ret=%i\n",_ret_
);
892 * The NtUserGetWindowDC function retrieves the device context (DC) for the
893 * entire window, including title bar, menus, and scroll bars. A window device
894 * context permits painting anywhere in a window, because the origin of the
895 * device context is the upper-left corner of the window instead of the client
902 NtUserGetWindowDC(HWND hWnd
)
904 return NtUserGetDCEx(hWnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
908 NtUserGetDC(HWND hWnd
)
910 DPRINT("NtUGetDC -> %x:%x\n", hWnd
, !hWnd
? DCX_CACHE
| DCX_WINDOW
: DCX_USESTYLE
);
912 return NtUserGetDCEx(hWnd
, NULL
, NULL
== hWnd
? DCX_CACHE
| DCX_WINDOW
: DCX_USESTYLE
);
916 * Select logical palette into device context.
917 * \param hDC handle to the device context
918 * \param hpal handle to the palette
919 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
920 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
921 * palette colors in the best way.
922 * \return old palette
924 * \todo implement ForceBackground == TRUE
928 NtUserSelectPalette(HDC hDC
,
930 BOOL ForceBackground
)
933 UserEnterExclusive();
934 // Implement window checks
935 oldPal
= GdiSelectPalette( hDC
, hpal
, ForceBackground
);