2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * PURPOSE: Monitor support
22 * FILE: subsys/win32k/ntuser/monitor.c
23 * PROGRAMER: Anich Gregor (blight@blight.eu.org)
28 /* INCLUDES ******************************************************************/
32 /* FIXME: find include file for these */
33 #define MONITORINFOF_PRIMARY 1
34 #define MONITOR_DEFAULTTONULL 0
35 #define MONITOR_DEFAULTTOPRIMARY 1
36 #define MONITOR_DEFAULTTONEAREST 2
41 /* GLOBALS *******************************************************************/
43 /* list of monitors */
44 static PMONITOR gMonitorList
= NULL
;
46 /* INITALIZATION FUNCTIONS ****************************************************/
51 DPRINT("Initializing monitor implementation...\n");
53 return STATUS_SUCCESS
;
59 DPRINT("Cleaning up monitor implementation...\n");
60 /* FIXME: Destroy monitor objects? */
62 return STATUS_SUCCESS
;
65 /* PRIVATE FUNCTIONS **********************************************************/
68 # define MIN(a, b) ((a) < (b) ? (a) : (b))
71 # define MAX(a, b) ((a) > (b) ? (a) : (b))
74 # define ABS(a) ((a) < (0) ? (-(a)) : (a))
77 /* IntCreateMonitorObject
82 * If the function succeeds a pointer to a MONITOR is returned. On failure
87 IntCreateMonitorObject()
92 Monitor
= UserCreateObject(gHandleTable
, NULL
, &Handle
, otMonitor
, sizeof (MONITOR
));
98 ExInitializeFastMutex(&Monitor
->Lock
);
103 /* IntDestroyMonitorObject
106 * You have to be the owner of the monitors lock to safely destroy it.
111 * Pointer to the MONITOR which shall be deleted
115 IntDestroyMonitorObject(IN PMONITOR pMonitor
)
117 RtlFreeUnicodeString(&pMonitor
->DeviceName
);
118 UserDereferenceObject(pMonitor
);
123 UserGetMonitorObject(IN HMONITOR hMonitor
)
129 SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE
);
134 Monitor
= (PMONITOR
)UserGetObject(gHandleTable
, hMonitor
, otMonitor
);
137 SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE
);
141 ASSERT(Monitor
->head
.cLockObj
>= 0);
149 * Creates a new MONITOR and appends it to the list of monitors.
153 * pGdiDevice Pointer to the PDEVOBJ onto which the monitor was attached
154 * DisplayNumber Display Number (starting with 0)
160 IntAttachMonitor(IN PDEVOBJ
*pGdiDevice
,
161 IN ULONG DisplayNumber
)
164 WCHAR Buffer
[CCHDEVICENAME
];
166 DPRINT("Attaching monitor...\n");
168 /* create new monitor object */
169 Monitor
= IntCreateMonitorObject();
172 DPRINT("Couldnt create monitor object\n");
173 return STATUS_INSUFFICIENT_RESOURCES
;
176 _snwprintf(Buffer
, CCHDEVICENAME
, L
"\\\\.\\DISPLAY%d", DisplayNumber
+ 1);
177 if (!RtlCreateUnicodeString(&Monitor
->DeviceName
, Buffer
))
179 DPRINT("Couldn't duplicate monitor name!\n");
180 UserDereferenceObject(Monitor
);
181 UserDeleteObject(UserHMGetHandle(Monitor
), otMonitor
);
182 return STATUS_INSUFFICIENT_RESOURCES
;
185 Monitor
->GdiDevice
= pGdiDevice
;
186 Monitor
->rcMonitor
.left
= 0;
187 Monitor
->rcMonitor
.top
= 0;
188 Monitor
->rcMonitor
.right
= Monitor
->rcMonitor
.left
+ pGdiDevice
->gdiinfo
.ulHorzRes
;
189 Monitor
->rcMonitor
.bottom
= Monitor
->rcMonitor
.top
+ pGdiDevice
->gdiinfo
.ulVertRes
;
190 Monitor
->rcWork
= Monitor
->rcMonitor
;
191 Monitor
->cWndStack
= 0;
193 Monitor
->hrgnMonitor
= NtGdiCreateRectRgn( Monitor
->rcMonitor
.left
,
194 Monitor
->rcMonitor
.top
,
195 Monitor
->rcMonitor
.right
,
196 Monitor
->rcMonitor
.bottom
);
198 // Replace with IntGdiSetRegeionOwner(Monitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC);
199 GDIOBJ_SetOwnership(Monitor
->hrgnMonitor
, NULL
);
201 if (gMonitorList
== NULL
)
203 DPRINT("Primary monitor is beeing attached\n");
204 Monitor
->IsPrimary
= TRUE
;
205 gMonitorList
= Monitor
;
210 DPRINT("Additional monitor is beeing attached\n");
211 for (p
= gMonitorList
; p
->Next
!= NULL
; p
= p
->Next
)
218 return STATUS_SUCCESS
;
223 * Deletes a MONITOR and removes it from the list of monitors.
227 * pGdiDevice Pointer to the PDEVOBJ from which the monitor was detached
233 IntDetachMonitor(IN PDEVOBJ
*pGdiDevice
)
237 for (Monitor
= gMonitorList
; Monitor
!= NULL
; Monitor
= Monitor
->Next
)
239 if (Monitor
->GdiDevice
== pGdiDevice
)
245 /* no monitor for given device found */
246 return STATUS_INVALID_PARAMETER
;
249 if (Monitor
->IsPrimary
&& (Monitor
->Next
!= NULL
|| Monitor
->Prev
!= NULL
))
251 PMONITOR NewPrimaryMonitor
= (Monitor
->Prev
!= NULL
) ? (Monitor
->Prev
) : (Monitor
->Next
);
253 ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&NewPrimaryMonitor
->Lock
);
254 NewPrimaryMonitor
->IsPrimary
= TRUE
;
255 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&NewPrimaryMonitor
->Lock
);
258 if (gMonitorList
== Monitor
)
260 gMonitorList
= Monitor
->Next
;
261 if (Monitor
->Next
!= NULL
)
262 Monitor
->Next
->Prev
= NULL
;
266 Monitor
->Prev
->Next
= Monitor
->Next
;
267 if (Monitor
->Next
!= NULL
)
268 Monitor
->Next
->Prev
= Monitor
->Prev
;
271 IntDestroyMonitorObject(Monitor
);
273 return STATUS_SUCCESS
;
276 /* IntGetPrimaryMonitor
278 * Returns a PMONITOR for the primary monitor
285 IntGetPrimaryMonitor()
289 for (Monitor
= gMonitorList
; Monitor
!= NULL
; Monitor
= Monitor
->Next
)
291 /* FIXME: I guess locking the monitor is not neccessary to read 1 int */
292 if (Monitor
->IsPrimary
)
299 /* IntGetMonitorsFromRect
301 * Returns a list of monitor handles/rectangles. The rectangles in the list are
302 * the areas of intersection with the monitors.
307 * Rectangle in desktop coordinates. If this is NULL all monitors are
308 * returned and the rect list is filled with the sizes of the monitors.
311 * Pointer to an array of HMONITOR which is filled with monitor handles.
315 * Pointer to an array of RECT which is filled with intersection rects in
316 * desktop coordinates.
317 * Can be NULL, will be ignored if no intersecting monitor is found and
318 * flags is MONITOR_DEFAULTTONEAREST
321 * Size of the hMonitorList and monitorRectList arguments. If this is zero
322 * hMonitorList and monitorRectList are ignored.
325 * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
328 * The number of monitors which intersect the specified region.
332 IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect
,
333 OPTIONAL OUT HMONITOR
*hMonitorList
,
334 OPTIONAL OUT PRECTL monitorRectList
,
335 OPTIONAL IN DWORD listSize
,
336 OPTIONAL IN DWORD flags
)
338 PMONITOR Monitor
, NearestMonitor
= NULL
, PrimaryMonitor
= NULL
;
340 LONG iNearestDistanceX
= 0x7fffffff, iNearestDistanceY
= 0x7fffffff;
342 /* find monitors which intersect the rectangle */
343 for (Monitor
= gMonitorList
; Monitor
!= NULL
; Monitor
= Monitor
->Next
)
345 RECTL MonitorRect
, IntersectionRect
;
347 ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&Monitor
->Lock
);
348 MonitorRect
.left
= 0; /* FIXME: get origin */
349 MonitorRect
.top
= 0; /* FIXME: get origin */
350 MonitorRect
.right
= MonitorRect
.left
+ Monitor
->GdiDevice
->gdiinfo
.ulHorzRes
;
351 MonitorRect
.bottom
= MonitorRect
.top
+ Monitor
->GdiDevice
->gdiinfo
.ulVertRes
;
352 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Monitor
->Lock
);
354 DPRINT("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
355 MonitorRect
.left
, MonitorRect
.top
, MonitorRect
.right
, MonitorRect
.bottom
);
357 if (flags
== MONITOR_DEFAULTTOPRIMARY
&& Monitor
->IsPrimary
)
359 PrimaryMonitor
= Monitor
;
364 BOOL intersects
= TRUE
;
366 /* check if the rect intersects the monitor */
367 if ((pRect
->right
< MonitorRect
.left
) || (pRect
->left
> MonitorRect
.right
) ||
368 (pRect
->bottom
< MonitorRect
.top
) || (pRect
->top
> MonitorRect
.bottom
))
373 if (flags
== MONITOR_DEFAULTTONEAREST
&& !intersects
)
375 INT distanceX
, distanceY
;
377 distanceX
= MIN(ABS(MonitorRect
.left
- pRect
->right
),
378 ABS(pRect
->left
- MonitorRect
.right
));
379 distanceY
= MIN(ABS(MonitorRect
.top
- pRect
->bottom
),
380 ABS(pRect
->top
- MonitorRect
.bottom
));
382 if (((distanceX
< iNearestDistanceX
) && (distanceY
<= iNearestDistanceY
)) ||
383 ((distanceX
<= iNearestDistanceX
) && (distanceY
< iNearestDistanceY
)))
385 iNearestDistanceX
= distanceX
;
386 iNearestDistanceY
= distanceY
;
387 NearestMonitor
= Monitor
;
394 /* calculate intersection */
395 IntersectionRect
.left
= MAX(MonitorRect
.left
, pRect
->left
);
396 IntersectionRect
.top
= MAX(MonitorRect
.top
, pRect
->top
);
397 IntersectionRect
.right
= MIN(MonitorRect
.right
, pRect
->right
);
398 IntersectionRect
.bottom
= MIN(MonitorRect
.bottom
, pRect
->bottom
);
402 IntersectionRect
= MonitorRect
;
405 if (iCount
< listSize
)
407 if (hMonitorList
!= NULL
)
408 hMonitorList
[iCount
] = UserHMGetHandle(Monitor
);
409 if (monitorRectList
!= NULL
)
410 monitorRectList
[iCount
] = IntersectionRect
;
415 if (iCount
== 0 && flags
== MONITOR_DEFAULTTONEAREST
)
417 if (iCount
< listSize
)
419 if (hMonitorList
!= NULL
)
420 hMonitorList
[iCount
] = UserHMGetHandle(NearestMonitor
);
424 else if (iCount
== 0 && flags
== MONITOR_DEFAULTTOPRIMARY
)
426 if (iCount
< listSize
)
428 if (hMonitorList
!= NULL
)
429 hMonitorList
[iCount
] = UserHMGetHandle(PrimaryMonitor
);
436 /* PUBLIC FUNCTIONS ***********************************************************/
438 /* NtUserEnumDisplayMonitors
440 * Enumerates display monitors which intersect the given HDC/cliprect
445 * Handle to a DC for which to enum intersecting monitors. If this is NULL
446 * it returns all monitors which are part of the current virtual screen.
449 * Clipping rectangle with coordinate system origin at the DCs origin if the
450 * given HDC is not NULL or in virtual screen coordinated if it is NULL.
454 * Pointer to an array of HMONITOR which is filled with monitor handles.
458 * Pointer to an array of RECT which is filled with intersection rectangles.
462 * Size of the hMonitorList and monitorRectList arguments. If this is zero
463 * hMonitorList and monitorRectList are ignored.
466 * The number of monitors which intersect the specified region or -1 on failure.
470 NtUserEnumDisplayMonitors(
472 OPTIONAL IN LPCRECTL pRect
,
473 OPTIONAL OUT HMONITOR
*hMonitorList
,
474 OPTIONAL OUT PRECTL monitorRectList
,
475 OPTIONAL IN DWORD listSize
)
478 HMONITOR
*safeHMonitorList
= NULL
;
479 PRECTL safeRectList
= NULL
;
487 status
= MmCopyFromCaller(&rect
, pRect
, sizeof (RECT
));
488 if (!NT_SUCCESS(status
))
490 DPRINT("MmCopyFromCaller() failed!\n");
491 SetLastNtError(status
);
502 /* get visible region bounding rect */
506 DPRINT("DC_LockDc() failed!\n");
507 /* FIXME: setlasterror? */
510 dcVisRgn
= dc
->rosdc
.hVisRgn
;
513 regionType
= NtGdiGetRgnBox(dcVisRgn
, &dcRect
);
516 DPRINT("NtGdiGetRgnBox() failed!\n");
519 if (regionType
== NULLREGION
)
521 if (regionType
== COMPLEXREGION
)
522 { /* TODO: warning */
525 /* if hDC and pRect are given the area of interest is pRect with
526 coordinate origin at the DC position */
529 rect
.left
+= dcRect
.left
;
530 rect
.right
+= dcRect
.left
;
531 rect
.top
+= dcRect
.top
;
532 rect
.bottom
+= dcRect
.top
;
534 /* if hDC is given and pRect is not the area of interest is the
535 bounding rect of hDC */
542 if (hDC
== NULL
&& pRect
== NULL
)
547 /* find intersecting monitors */
548 numMonitors
= IntGetMonitorsFromRect(myRect
, NULL
, NULL
, 0, 0);
549 if (numMonitors
== 0 || listSize
== 0 ||
550 (hMonitorList
== NULL
&& monitorRectList
== NULL
))
552 DPRINT("numMonitors = %d\n", numMonitors
);
556 if (hMonitorList
!= NULL
&& listSize
!= 0)
558 safeHMonitorList
= ExAllocatePool(PagedPool
, sizeof (HMONITOR
) * listSize
);
559 if (safeHMonitorList
== NULL
)
561 /* FIXME: SetLastWin32Error? */
565 if (monitorRectList
!= NULL
&& listSize
!= 0)
567 safeRectList
= ExAllocatePool(PagedPool
, sizeof (RECT
) * listSize
);
568 if (safeRectList
== NULL
)
570 ExFreePool(safeHMonitorList
);
571 /* FIXME: SetLastWin32Error? */
576 /* get intersecting monitors */
577 numMonitors
= IntGetMonitorsFromRect(myRect
, safeHMonitorList
, safeRectList
,
580 if (hDC
!= NULL
&& pRect
!= NULL
&& safeRectList
!= NULL
)
581 for (i
= 0; i
< numMonitors
; i
++)
583 safeRectList
[i
].left
-= dcRect
.left
;
584 safeRectList
[i
].right
-= dcRect
.left
;
585 safeRectList
[i
].top
-= dcRect
.top
;
586 safeRectList
[i
].bottom
-= dcRect
.top
;
590 if (hMonitorList
!= NULL
&& listSize
!= 0)
592 status
= MmCopyToCaller(hMonitorList
, safeHMonitorList
, sizeof (HMONITOR
) * listSize
);
593 ExFreePool(safeHMonitorList
);
594 if (!NT_SUCCESS(status
))
596 ExFreePool(safeRectList
);
597 SetLastNtError(status
);
601 if (monitorRectList
!= NULL
&& listSize
!= 0)
603 status
= MmCopyToCaller(monitorRectList
, safeRectList
, sizeof (RECT
) * listSize
);
604 ExFreePool(safeRectList
);
605 if (!NT_SUCCESS(status
))
607 SetLastNtError(status
);
615 /* NtUserGetMonitorInfo
617 * Retrieves information about a given monitor
622 * Handle to a monitor for which to get information
625 * Pointer to a MONITORINFO struct which is filled with the information.
626 * The cbSize member must be set to sizeof(MONITORINFO) or
627 * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
628 * from MONITORINFO will be filled.
631 * Pointer to a UNICODE_STRING which will recieve the device's name. The
632 * length should be CCHDEVICENAME
636 * TRUE on success; FALSE on failure (calls SetLastNtError())
641 NtUserGetMonitorInfo(
642 IN HMONITOR hMonitor
,
643 OUT LPMONITORINFO pMonitorInfo
)
646 MONITORINFOEXW MonitorInfo
;
648 DECLARE_RETURN(BOOL
);
650 DPRINT("Enter NtUserGetMonitorInfo\n");
653 /* get monitor object */
654 if (!(Monitor
= UserGetMonitorObject(hMonitor
)))
656 DPRINT("Couldnt find monitor 0x%lx\n", hMonitor
);
660 if(pMonitorInfo
== NULL
)
662 SetLastNtError(STATUS_INVALID_PARAMETER
);
666 /* get size of pMonitorInfo */
667 Status
= MmCopyFromCaller(&MonitorInfo
.cbSize
, &pMonitorInfo
->cbSize
, sizeof (MonitorInfo
.cbSize
));
668 if (!NT_SUCCESS(Status
))
670 SetLastNtError(Status
);
673 if ((MonitorInfo
.cbSize
!= sizeof (MONITORINFO
)) &&
674 (MonitorInfo
.cbSize
!= sizeof (MONITORINFOEXW
)))
676 SetLastNtError(STATUS_INVALID_PARAMETER
);
680 /* fill monitor info */
681 MonitorInfo
.rcMonitor
.left
= 0; /* FIXME: get origin */
682 MonitorInfo
.rcMonitor
.top
= 0; /* FIXME: get origin */
683 MonitorInfo
.rcMonitor
.right
= MonitorInfo
.rcMonitor
.left
+ Monitor
->GdiDevice
->gdiinfo
.ulHorzRes
;
684 MonitorInfo
.rcMonitor
.bottom
= MonitorInfo
.rcMonitor
.top
+ Monitor
->GdiDevice
->gdiinfo
.ulVertRes
;
685 MonitorInfo
.rcWork
= MonitorInfo
.rcMonitor
; /* FIXME: use DEVMODE panning to calculate work area? */
686 MonitorInfo
.dwFlags
= 0;
688 if (Monitor
->IsPrimary
)
689 MonitorInfo
.dwFlags
|= MONITORINFOF_PRIMARY
;
691 /* fill device name */
692 if (MonitorInfo
.cbSize
== sizeof (MONITORINFOEXW
))
695 INT len
= Monitor
->DeviceName
.Length
;
696 if (len
>= CCHDEVICENAME
* sizeof (WCHAR
))
697 len
= (CCHDEVICENAME
- 1) * sizeof (WCHAR
);
699 memcpy(MonitorInfo
.szDevice
, Monitor
->DeviceName
.Buffer
, len
);
700 memcpy(MonitorInfo
.szDevice
+ (len
/ sizeof (WCHAR
)), &nul
, sizeof (WCHAR
));
704 Status
= MmCopyToCaller(pMonitorInfo
, &MonitorInfo
, MonitorInfo
.cbSize
);
705 if (!NT_SUCCESS(Status
))
707 DPRINT("GetMonitorInfo: MmCopyToCaller failed\n");
708 SetLastNtError(Status
);
712 DPRINT("GetMonitorInfo: success\n");
717 DPRINT("Leave NtUserGetMonitorInfo, ret=%i\n",_ret_
);
722 /* NtUserMonitorFromPoint
724 * Returns a handle to the monitor containing the given point.
729 * Point for which to find monitor
732 * Specifies the behaviour if the point isn't on any of the monitors.
735 * If the point is found a handle to the monitor is returned; if not the
736 * return value depends on dwFlags
740 NtUserMonitorFromPoint(
746 HMONITOR hMonitor
= NULL
;
749 InRect
.left
= InRect
.right
= point
.x
;
750 InRect
.top
= InRect
.bottom
= point
.y
;
752 /* find intersecting monitor */
753 NumMonitors
= IntGetMonitorsFromRect(&InRect
, &hMonitor
, NULL
, 1, 0);
756 return (HMONITOR
)NULL
;
759 if (hMonitor
== NULL
)
761 if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
)
763 PMONITOR MonitorObj
= IntGetPrimaryMonitor();
765 hMonitor
= UserHMGetHandle(MonitorObj
);
767 else if (dwFlags
== MONITOR_DEFAULTTONEAREST
)
769 NumMonitors
= IntGetMonitorsFromRect(&InRect
, &hMonitor
, NULL
,
770 1, MONITOR_DEFAULTTONEAREST
);
771 /*ASSERT( (numMonitors > 0) && (hMonitor != NULL) );*/
773 /* else flag is DEFAULTTONULL */
779 /* NtUserMonitorFromRect
781 * Returns a handle to the monitor having the largest intersection with a
787 * Pointer to a RECT for which to find monitor
790 * Specifies the behaviour if no monitor intersects the given rect
793 * If a monitor intersects the rect a handle to it is returned; if not the
794 * return value depends on dwFlags
798 NtUserMonitorFromRect(
802 INT numMonitors
, iLargestArea
= -1, i
;
804 HMONITOR
*hMonitorList
;
805 HMONITOR hMonitor
= NULL
;
810 status
= MmCopyFromCaller(&rect
, pRect
, sizeof (RECT
));
811 if (!NT_SUCCESS(status
))
813 SetLastNtError(status
);
814 return (HMONITOR
)NULL
;
817 /* find intersecting monitors */
818 numMonitors
= IntGetMonitorsFromRect(&rect
, NULL
, NULL
, 0, 0);
821 return (HMONITOR
)NULL
;
824 if (numMonitors
== 0)
826 if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
)
828 PMONITOR monitorObj
= IntGetPrimaryMonitor();
830 return UserHMGetHandle(monitorObj
);
832 else if (dwFlags
== MONITOR_DEFAULTTONEAREST
)
834 numMonitors
= IntGetMonitorsFromRect(&rect
, &hMonitor
, NULL
,
835 1, MONITOR_DEFAULTTONEAREST
);
836 if (numMonitors
<= 0)
839 return (HMONITOR
)NULL
;
845 /* else flag is DEFAULTTONULL */
846 return (HMONITOR
)NULL
;
849 hMonitorList
= ExAllocatePool(PagedPool
, sizeof (HMONITOR
) * numMonitors
);
850 if (hMonitorList
== NULL
)
852 /* FIXME: SetLastWin32Error? */
853 return (HMONITOR
)NULL
;
855 rectList
= ExAllocatePool(PagedPool
, sizeof (RECT
) * numMonitors
);
856 if (rectList
== NULL
)
858 ExFreePool(hMonitorList
);
859 /* FIXME: SetLastWin32Error? */
860 return (HMONITOR
)NULL
;
863 /* get intersecting monitors */
864 numMonitors
= IntGetMonitorsFromRect(&rect
, hMonitorList
, rectList
,
866 if (numMonitors
<= 0)
868 ExFreePool(hMonitorList
);
869 ExFreePool(rectList
);
870 return (HMONITOR
)NULL
;
873 /* find largest intersection */
874 for (i
= 0; i
< numMonitors
; i
++)
876 INT area
= (rectList
[i
].right
- rectList
[i
].left
) *
877 (rectList
[i
].bottom
- rectList
[i
].top
);
878 if (area
> iLargestArea
)
880 hMonitor
= hMonitorList
[i
];
884 ExFreePool(hMonitorList
);
885 ExFreePool(rectList
);
893 NtUserMonitorFromWindow(
897 PWINDOW_OBJECT Window
;
898 HMONITOR hMonitor
= NULL
;
900 DECLARE_RETURN(HMONITOR
);
902 DPRINT("Enter NtUserMonitorFromWindow\n");
905 if (!(Window
= UserGetWindowObject(hWnd
)))
907 if (dwFlags
== MONITOR_DEFAULTTONULL
)
911 IntGetMonitorsFromRect(NULL
, &hMonitor
, NULL
, 1, dwFlags
);
918 Rect
.left
= Rect
.right
= Window
->Wnd
->rcWindow
.left
;
919 Rect
.top
= Rect
.bottom
= Window
->Wnd
->rcWindow
.bottom
;
921 IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
926 DPRINT("Leave NtUserMonitorFromWindow, ret=%i\n",_ret_
);