win32u: Move monitor_from_rect implementation from user32.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2022-02-14 14:07:14 +01:00 committed by Alexandre Julliard
parent c6d1921e93
commit db8fcc1c9d
3 changed files with 70 additions and 78 deletions

View file

@ -989,89 +989,12 @@ BOOL WINAPI PhysicalToLogicalPointForPerMonitorDPI( HWND hwnd, POINT *pt )
return ret;
}
struct monitor_enum_info
{
RECT rect;
UINT max_area;
UINT min_distance;
HMONITOR primary;
HMONITOR nearest;
HMONITOR ret;
};
/* helper callback for MonitorFromRect */
static BOOL CALLBACK monitor_enum( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lp )
{
struct monitor_enum_info *info = (struct monitor_enum_info *)lp;
RECT intersect;
if (IntersectRect( &intersect, rect, &info->rect ))
{
/* check for larger intersecting area */
UINT area = (intersect.right - intersect.left) * (intersect.bottom - intersect.top);
if (area > info->max_area)
{
info->max_area = area;
info->ret = monitor;
}
}
else if (!info->max_area) /* if not intersecting, check for min distance */
{
UINT distance;
UINT x, y;
if (info->rect.right <= rect->left) x = rect->left - info->rect.right;
else if (rect->right <= info->rect.left) x = info->rect.left - rect->right;
else x = 0;
if (info->rect.bottom <= rect->top) y = rect->top - info->rect.bottom;
else if (rect->bottom <= info->rect.top) y = info->rect.top - rect->bottom;
else y = 0;
distance = x * x + y * y;
if (distance < info->min_distance)
{
info->min_distance = distance;
info->nearest = monitor;
}
}
if (!info->primary)
{
MONITORINFO mon_info;
mon_info.cbSize = sizeof(mon_info);
GetMonitorInfoW( monitor, &mon_info );
if (mon_info.dwFlags & MONITORINFOF_PRIMARY) info->primary = monitor;
}
return TRUE;
}
/***********************************************************************
* MonitorFromRect (USER32.@)
*/
HMONITOR WINAPI MonitorFromRect( const RECT *rect, DWORD flags )
{
struct monitor_enum_info info;
info.rect = *rect;
info.max_area = 0;
info.min_distance = ~0u;
info.primary = 0;
info.nearest = 0;
info.ret = 0;
if (IsRectEmpty(&info.rect))
{
info.rect.right = info.rect.left + 1;
info.rect.bottom = info.rect.top + 1;
}
if (!NtUserEnumDisplayMonitors( 0, NULL, monitor_enum, (LPARAM)&info )) return 0;
if (!info.ret)
{
if (flags & MONITOR_DEFAULTTOPRIMARY) info.ret = info.primary;
else if (flags & MONITOR_DEFAULTTONEAREST) info.ret = info.nearest;
}
TRACE( "%s flags %x returning %p\n", wine_dbgstr_rect(rect), flags, info.ret );
return info.ret;
return UlongToHandle( NtUserCallTwoParam( (LONG_PTR)rect, flags, NtUserMonitorFromRect ));
}
/***********************************************************************

View file

@ -1936,6 +1936,72 @@ static BOOL get_monitor_info( HMONITOR handle, MONITORINFO *info )
return FALSE;
}
static HMONITOR monitor_from_rect( const RECT *rect, DWORD flags, UINT dpi )
{
HMONITOR primary = 0, nearest = 0, ret = 0;
UINT max_area = 0, min_distance = ~0u;
struct monitor *monitor;
RECT r;
r = map_dpi_rect( *rect, dpi, system_dpi );
if (is_rect_empty( &r ))
{
r.right = r.left + 1;
r.bottom = r.top + 1;
}
if (!lock_display_devices()) return 0;
LIST_FOR_EACH_ENTRY(monitor, &monitors, struct monitor, entry)
{
RECT intersect;
RECT monitor_rect = map_dpi_rect( monitor->rc_monitor, get_monitor_dpi( monitor->handle ),
system_dpi );
if (intersect_rect( &intersect, &monitor_rect, &r ))
{
/* check for larger intersecting area */
UINT area = (intersect.right - intersect.left) * (intersect.bottom - intersect.top);
if (area > max_area)
{
max_area = area;
ret = monitor->handle;
}
}
else if (!max_area) /* if not intersecting, check for min distance */
{
UINT distance;
UINT x, y;
if (r.right <= monitor_rect.left) x = monitor_rect.left - r.right;
else if (monitor_rect.right <= r.left) x = r.left - monitor_rect.right;
else x = 0;
if (r.bottom <= monitor_rect.top) y = monitor_rect.top - r.bottom;
else if (monitor_rect.bottom <= r.top) y = r.top - monitor_rect.bottom;
else y = 0;
distance = x * x + y * y;
if (distance < min_distance)
{
min_distance = distance;
nearest = monitor->handle;
}
}
if (monitor->flags & MONITORINFOF_PRIMARY) primary = monitor->handle;
}
unlock_display_devices();
if (!ret)
{
if (flags & MONITOR_DEFAULTTOPRIMARY) ret = primary;
else if (flags & MONITOR_DEFAULTTONEAREST) ret = nearest;
}
TRACE( "%s flags %x returning %p\n", wine_dbgstr_rect(rect), flags, ret );
return ret;
}
/***********************************************************************
* NtUserGetSystemDpiForProcess (win32u.@)
*/
@ -4427,6 +4493,8 @@ ULONG_PTR WINAPI NtUserCallTwoParam( ULONG_PTR arg1, ULONG_PTR arg2, ULONG code
return get_system_metrics_for_dpi( arg1, arg2 );
case NtUserMirrorRgn:
return mirror_window_region( UlongToHandle(arg1), UlongToHandle(arg2) );
case NtUserMonitorFromRect:
return HandleToUlong( monitor_from_rect( (const RECT *)arg1, arg2, get_thread_dpi() ));
default:
FIXME( "invalid code %u\n", code );
return 0;

View file

@ -67,6 +67,7 @@ enum
NtUserGetMonitorInfo,
NtUserGetSystemMetricsForDpi,
NtUserMirrorRgn,
NtUserMonitorFromRect,
};
/* color index used to retrieve system 55aa brush */