Improve the code to enumerate monitors.
- Don't use custom MIN / MAX / ABS macros
- Calculate distance by r^2 = x^2 + y^2
- Use RECTL_bIntersectRect instead of code duplication
- Fix possible NULL pointer dereference
- pass bottom-right exclusive rect to IntGetMonitorsFromRect from NtUserMonitorFromPoint
- Don't handle MONITOR_DEFAULTTOPRIMARY and MONITOR_DEFAULTTONEAREST twice
- Use unsigned variables for unsigned values
- Don't check the result of a UINT returning function for < 0
- Improve readability

svn path=/trunk/; revision=49310
This commit is contained in:
Timo Kreuzer 2010-10-27 17:16:11 +00:00
parent 72f80d0c80
commit 1c363f5fbe

View file

@ -47,16 +47,6 @@ CleanupMonitorImpl()
/* PRIVATE FUNCTIONS **********************************************************/ /* PRIVATE FUNCTIONS **********************************************************/
#ifndef MIN
# define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef ABS
# define ABS(a) ((a) < (0) ? (-(a)) : (a))
#endif
/* IntCreateMonitorObject /* IntCreateMonitorObject
* *
* Creates a MONITOR * Creates a MONITOR
@ -318,9 +308,9 @@ IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect,
{ {
PMONITOR Monitor, NearestMonitor = NULL, PrimaryMonitor = NULL; PMONITOR Monitor, NearestMonitor = NULL, PrimaryMonitor = NULL;
UINT iCount = 0; UINT iCount = 0;
LONG iNearestDistanceX = 0x7fffffff, iNearestDistanceY = 0x7fffffff; ULONG iNearestDistance = 0xffffffff;
/* find monitors which intersect the rectangle */ /* Find monitors which intersect the rectangle */
for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next) for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next)
{ {
RECTL MonitorRect, IntersectionRect; RECTL MonitorRect, IntersectionRect;
@ -337,49 +327,42 @@ IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect,
PrimaryMonitor = Monitor; PrimaryMonitor = Monitor;
} }
if (pRect != NULL) /* Check if a rect is given */
if (pRect == NULL)
{ {
BOOL intersects = TRUE; /* No rect given, so use the full monitor rect */
IntersectionRect = MonitorRect;
}
/* check if the rect intersects the monitor */ /* We have a rect, calculate intersection */
if ((pRect->right < MonitorRect.left) || (pRect->left > MonitorRect.right) || else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect))
(pRect->bottom < MonitorRect.top) || (pRect->top > MonitorRect.bottom)) {
/* Rects did not intersect */
if (flags == MONITOR_DEFAULTTONEAREST)
{ {
intersects = FALSE; ULONG cx, cy, iDistance;
}
if (flags == MONITOR_DEFAULTTONEAREST && !intersects) /* Get x and y distance */
{ cx = min(abs(MonitorRect.left - pRect->right),
INT distanceX, distanceY; abs(pRect->left - MonitorRect.right));
cy = min(abs(MonitorRect.top - pRect->bottom),
abs(pRect->top - MonitorRect.bottom));
distanceX = MIN(ABS(MonitorRect.left - pRect->right), /* Calculate distance square */
ABS(pRect->left - MonitorRect.right)); iDistance = cx * cx + cy * cy;
distanceY = MIN(ABS(MonitorRect.top - pRect->bottom),
ABS(pRect->top - MonitorRect.bottom));
if (((distanceX < iNearestDistanceX) && (distanceY <= iNearestDistanceY)) || /* Check if this is the new nearest monitor */
((distanceX <= iNearestDistanceX) && (distanceY < iNearestDistanceY))) if (iDistance < iNearestDistance)
{ {
iNearestDistanceX = distanceX; iNearestDistance = iDistance;
iNearestDistanceY = distanceY;
NearestMonitor = Monitor; NearestMonitor = Monitor;
} }
} }
if (!intersects) continue;
continue;
/* calculate intersection */
IntersectionRect.left = MAX(MonitorRect.left, pRect->left);
IntersectionRect.top = MAX(MonitorRect.top, pRect->top);
IntersectionRect.right = MIN(MonitorRect.right, pRect->right);
IntersectionRect.bottom = MIN(MonitorRect.bottom, pRect->bottom);
}
else
{
IntersectionRect = MonitorRect;
} }
/* Check if there's space in the buffer */
if (iCount < listSize) if (iCount < listSize)
{ {
if (hMonitorList != NULL) if (hMonitorList != NULL)
@ -387,27 +370,30 @@ IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect,
if (monitorRectList != NULL) if (monitorRectList != NULL)
monitorRectList[iCount] = IntersectionRect; monitorRectList[iCount] = IntersectionRect;
} }
/* Increase count of found monitors */
iCount++; iCount++;
} }
if (iCount == 0 && flags == MONITOR_DEFAULTTONEAREST) /* Found nothing intersecting? */
if (iCount == 0)
{ {
if (iCount < listSize) /* Check if we shall default to the nearest monitor */
if (flags == MONITOR_DEFAULTTONEAREST && NearestMonitor)
{ {
if (hMonitorList != NULL) if (hMonitorList && listSize > 0)
hMonitorList[iCount] = UserHMGetHandle(NearestMonitor); hMonitorList[iCount] = UserHMGetHandle(NearestMonitor);
iCount++;
} }
iCount++; /* Check if we shall default to the primary monitor */
} else if (flags == MONITOR_DEFAULTTOPRIMARY && PrimaryMonitor)
else if (iCount == 0 && flags == MONITOR_DEFAULTTOPRIMARY)
{
if (iCount < listSize)
{ {
if (hMonitorList != NULL) if (hMonitorList != NULL && listSize > 0)
hMonitorList[iCount] = UserHMGetHandle(PrimaryMonitor); hMonitorList[iCount] = UserHMGetHandle(PrimaryMonitor);
iCount++;
} }
iCount++;
} }
return iCount; return iCount;
} }
@ -719,34 +705,19 @@ NtUserMonitorFromPoint(
RECTL InRect; RECTL InRect;
HMONITOR hMonitor = NULL; HMONITOR hMonitor = NULL;
/* fill inRect */ /* fill inRect (bottom-right exclusive) */
InRect.left = InRect.right = point.x; InRect.left = point.x;
InRect.top = InRect.bottom = point.y; InRect.right = point.x + 1;
InRect.top = point.y;
InRect.bottom = point.y + 1;
/* find intersecting monitor */ /* find intersecting monitor */
NumMonitors = IntGetMonitorsFromRect(&InRect, &hMonitor, NULL, 1, 0); NumMonitors = IntGetMonitorsFromRect(&InRect, &hMonitor, NULL, 1, dwFlags);
if (NumMonitors < 0) if (NumMonitors < 0)
{ {
return (HMONITOR)NULL; return (HMONITOR)NULL;
} }
if (hMonitor == NULL)
{
if (dwFlags == MONITOR_DEFAULTTOPRIMARY)
{
PMONITOR MonitorObj = IntGetPrimaryMonitor();
if (MonitorObj)
hMonitor = UserHMGetHandle(MonitorObj);
}
else if (dwFlags == MONITOR_DEFAULTTONEAREST)
{
NumMonitors = IntGetMonitorsFromRect(&InRect, &hMonitor, NULL,
1, MONITOR_DEFAULTTONEAREST);
/*ASSERT( (numMonitors > 0) && (hMonitor != NULL) );*/
}
/* else flag is DEFAULTTONULL */
}
return hMonitor; return hMonitor;
} }
@ -773,7 +744,7 @@ NtUserMonitorFromRect(
IN LPCRECTL pRect, IN LPCRECTL pRect,
IN DWORD dwFlags) IN DWORD dwFlags)
{ {
INT numMonitors, iLargestArea = -1, i; ULONG numMonitors, iLargestArea = 0, i;
PRECTL rectList; PRECTL rectList;
HMONITOR *hMonitorList; HMONITOR *hMonitorList;
HMONITOR hMonitor = NULL; HMONITOR hMonitor = NULL;
@ -789,44 +760,24 @@ NtUserMonitorFromRect(
} }
/* find intersecting monitors */ /* find intersecting monitors */
numMonitors = IntGetMonitorsFromRect(&rect, NULL, NULL, 0, 0); numMonitors = IntGetMonitorsFromRect(&rect, &hMonitor, NULL, 1, dwFlags);
if (numMonitors < 0) if (numMonitors <= 1)
{ {
return (HMONITOR)NULL; return hMonitor;
} }
if (numMonitors == 0) hMonitorList = ExAllocatePoolWithTag(PagedPool,
{ sizeof(HMONITOR) * numMonitors,
if (dwFlags == MONITOR_DEFAULTTOPRIMARY) USERTAG_MONITORRECTS);
{
PMONITOR monitorObj = IntGetPrimaryMonitor();
if (monitorObj)
return UserHMGetHandle(monitorObj);
}
else if (dwFlags == MONITOR_DEFAULTTONEAREST)
{
numMonitors = IntGetMonitorsFromRect(&rect, &hMonitor, NULL,
1, MONITOR_DEFAULTTONEAREST);
if (numMonitors <= 0)
{
/* error? */
return (HMONITOR)NULL;
}
if (numMonitors > 0)
return hMonitor;
}
/* else flag is DEFAULTTONULL */
return (HMONITOR)NULL;
}
hMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (HMONITOR) * numMonitors, USERTAG_MONITORRECTS);
if (hMonitorList == NULL) if (hMonitorList == NULL)
{ {
/* FIXME: SetLastWin32Error? */ /* FIXME: SetLastWin32Error? */
return (HMONITOR)NULL; return (HMONITOR)NULL;
} }
rectList = ExAllocatePoolWithTag(PagedPool, sizeof (RECT) * numMonitors, USERTAG_MONITORRECTS);
rectList = ExAllocatePoolWithTag(PagedPool,
sizeof(RECT) * numMonitors,
USERTAG_MONITORRECTS);
if (rectList == NULL) if (rectList == NULL)
{ {
ExFreePoolWithTag(hMonitorList, USERTAG_MONITORRECTS); ExFreePoolWithTag(hMonitorList, USERTAG_MONITORRECTS);
@ -837,7 +788,7 @@ NtUserMonitorFromRect(
/* get intersecting monitors */ /* get intersecting monitors */
numMonitors = IntGetMonitorsFromRect(&rect, hMonitorList, rectList, numMonitors = IntGetMonitorsFromRect(&rect, hMonitorList, rectList,
numMonitors, 0); numMonitors, 0);
if (numMonitors <= 0) if (numMonitors == 0)
{ {
ExFreePoolWithTag(hMonitorList, USERTAG_MONITORRECTS); ExFreePoolWithTag(hMonitorList, USERTAG_MONITORRECTS);
ExFreePoolWithTag(rectList, USERTAG_MONITORRECTS); ExFreePoolWithTag(rectList, USERTAG_MONITORRECTS);
@ -847,9 +798,9 @@ NtUserMonitorFromRect(
/* find largest intersection */ /* find largest intersection */
for (i = 0; i < numMonitors; i++) for (i = 0; i < numMonitors; i++)
{ {
INT area = (rectList[i].right - rectList[i].left) * ULONG area = (rectList[i].right - rectList[i].left) *
(rectList[i].bottom - rectList[i].top); (rectList[i].bottom - rectList[i].top);
if (area > iLargestArea) if (area >= iLargestArea)
{ {
hMonitor = hMonitorList[i]; hMonitor = hMonitorList[i];
} }