user: Moved GetMonitorInfo and EnumDisplayMonitors to the display driver.

Added Xinerama support for these functions.
This commit is contained in:
Alexandre Julliard 2006-10-23 13:51:30 +02:00
parent 3c305f9db9
commit 8a8903516c
5 changed files with 183 additions and 104 deletions

View File

@ -101,7 +101,9 @@ static const USER_DRIVER *load_driver(void)
GET_USER_FUNC(GetClipboardFormatName);
GET_USER_FUNC(EndClipboardUpdate);
GET_USER_FUNC(ChangeDisplaySettingsEx);
GET_USER_FUNC(EnumDisplayMonitors);
GET_USER_FUNC(EnumDisplaySettingsEx);
GET_USER_FUNC(GetMonitorInfo);
GET_USER_FUNC(CreateDesktopWindow);
GET_USER_FUNC(CreateWindow);
GET_USER_FUNC(DestroyWindow);
@ -290,11 +292,21 @@ static LONG nulldrv_ChangeDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode, HWND
return DISP_CHANGE_FAILED;
}
static BOOL nulldrv_EnumDisplayMonitors( HDC hdc, LPRECT rect, MONITORENUMPROC proc, LPARAM lp )
{
return FALSE;
}
static BOOL nulldrv_EnumDisplaySettingsEx( LPCWSTR name, DWORD num, LPDEVMODEW mode, DWORD flags )
{
return FALSE;
}
static BOOL nulldrv_GetMonitorInfo( HMONITOR handle, LPMONITORINFO info )
{
return FALSE;
}
static BOOL nulldrv_CreateDesktopWindow( HWND hwnd )
{
return TRUE;
@ -435,7 +447,9 @@ static const USER_DRIVER null_driver =
nulldrv_SetClipboardData,
/* display modes */
nulldrv_ChangeDisplaySettingsEx,
nulldrv_EnumDisplayMonitors,
nulldrv_EnumDisplaySettingsEx,
nulldrv_GetMonitorInfo,
/* windowing functions */
nulldrv_CreateDesktopWindow,
nulldrv_CreateWindow,
@ -612,11 +626,21 @@ static LONG loaderdrv_ChangeDisplaySettingsEx( LPCWSTR name, LPDEVMODEW mode, HW
return load_driver()->pChangeDisplaySettingsEx( name, mode, hwnd, flags, lparam );
}
static BOOL loaderdrv_EnumDisplayMonitors( HDC hdc, LPRECT rect, MONITORENUMPROC proc, LPARAM lp )
{
return load_driver()->pEnumDisplayMonitors( hdc, rect, proc, lp );
}
static BOOL loaderdrv_EnumDisplaySettingsEx( LPCWSTR name, DWORD num, LPDEVMODEW mode, DWORD flags )
{
return load_driver()->pEnumDisplaySettingsEx( name, num, mode, flags );
}
static BOOL loaderdrv_GetMonitorInfo( HMONITOR handle, LPMONITORINFO info )
{
return load_driver()->pGetMonitorInfo( handle, info );
}
static BOOL loaderdrv_CreateDesktopWindow( HWND hwnd )
{
return load_driver()->pCreateDesktopWindow( hwnd );
@ -745,7 +769,9 @@ static const USER_DRIVER lazy_load_driver =
loaderdrv_SetClipboardData,
/* display modes */
loaderdrv_ChangeDisplaySettingsEx,
loaderdrv_EnumDisplayMonitors,
loaderdrv_EnumDisplaySettingsEx,
loaderdrv_GetMonitorInfo,
/* windowing functions */
loaderdrv_CreateDesktopWindow,
loaderdrv_CreateWindow,

View File

@ -29,6 +29,7 @@
#include "winuser.h"
#include "winnls.h"
#include "winternl.h"
#include "user_private.h"
#include "wine/unicode.h"
#include "wine/debug.h"
@ -56,8 +57,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(win);
#define USIG_PROCESS_RUNNING 0x0500
#define USIG_PROCESS_LOADED 0x0600
#define xPRIMARY_MONITOR ((HMONITOR)0x12340042)
/***********************************************************************
* SignalProc32 (USER.391)
* UserSignalProc (USER32.@)
@ -339,36 +338,85 @@ BOOL WINAPI EnumDisplayDevicesW( LPCWSTR lpDevice, DWORD i, LPDISPLAY_DEVICEW lp
return TRUE;
}
/***********************************************************************
* MonitorFromPoint (USER32.@)
*/
HMONITOR WINAPI MonitorFromPoint(POINT ptScreenCoords, DWORD dwFlags)
struct monitor_enum_info
{
if ((dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
((ptScreenCoords.x >= 0) &&
(ptScreenCoords.x < GetSystemMetrics(SM_CXSCREEN)) &&
(ptScreenCoords.y >= 0) &&
(ptScreenCoords.y < GetSystemMetrics(SM_CYSCREEN))))
RECT rect;
UINT max_area;
UINT min_distance;
HMONITOR primary;
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 ))
{
return xPRIMARY_MONITOR;
/* 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;
}
}
return NULL;
else if (!info->max_area) /* if not intersecting, check for min distance */
{
UINT distance;
INT x, y;
if (rect->left >= info->rect.right) x = info->rect.right - rect->left;
else x = rect->right - info->rect.left;
if (rect->top >= info->rect.bottom) y = info->rect.bottom - rect->top;
else y = rect->bottom - info->rect.top;
distance = x * x + y * y;
if (distance < info->min_distance)
{
info->min_distance = distance;
info->ret = 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(LPRECT lprcScreenCoords, DWORD dwFlags)
HMONITOR WINAPI MonitorFromRect( LPRECT rect, DWORD flags )
{
if ((dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
((lprcScreenCoords->right > 0) &&
(lprcScreenCoords->bottom > 0) &&
(lprcScreenCoords->left < GetSystemMetrics(SM_CXSCREEN)) &&
(lprcScreenCoords->top < GetSystemMetrics(SM_CYSCREEN))))
{
return xPRIMARY_MONITOR;
}
return NULL;
struct monitor_enum_info info;
info.rect = *rect;
info.max_area = 0;
info.min_distance = ~0u;
info.primary = 0;
info.ret = 0;
if (!EnumDisplayMonitors( 0, NULL, monitor_enum, (LPARAM)&info )) return 0;
if (!info.ret && (flags & MONITOR_DEFAULTTOPRIMARY)) info.ret = info.primary;
TRACE( "%s flags %x returning %p\n", wine_dbgstr_rect(rect), flags, info.ret );
return info.ret;
}
/***********************************************************************
* MonitorFromPoint (USER32.@)
*/
HMONITOR WINAPI MonitorFromPoint( POINT pt, DWORD flags )
{
RECT rect;
SetRect( &rect, pt.x, pt.y, pt.x + 1, pt.y + 1 );
return MonitorFromRect( &rect, flags );
}
/***********************************************************************
@ -376,19 +424,14 @@ HMONITOR WINAPI MonitorFromRect(LPRECT lprcScreenCoords, DWORD dwFlags)
*/
HMONITOR WINAPI MonitorFromWindow(HWND hWnd, DWORD dwFlags)
{
RECT rect;
WINDOWPLACEMENT wp;
if (dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST))
return xPRIMARY_MONITOR;
if (IsIconic(hWnd) && GetWindowPlacement(hWnd, &wp))
return MonitorFromRect( &wp.rcNormalPosition, dwFlags );
if (IsIconic(hWnd) ?
GetWindowPlacement(hWnd, &wp) :
GetWindowRect(hWnd, &wp.rcNormalPosition)) {
return MonitorFromRect(&wp.rcNormalPosition, dwFlags);
}
return NULL;
GetWindowRect( hWnd, &rect );
return MonitorFromRect( &rect, dwFlags );
}
/***********************************************************************
@ -418,81 +461,15 @@ BOOL WINAPI GetMonitorInfoA(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)
*/
BOOL WINAPI GetMonitorInfoW(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)
{
RECT rcWork;
if ((hMonitor == xPRIMARY_MONITOR) &&
lpMonitorInfo &&
(lpMonitorInfo->cbSize >= sizeof(MONITORINFO)) &&
SystemParametersInfoW(SPI_GETWORKAREA, 0, &rcWork, 0))
{
SetRect( &lpMonitorInfo->rcMonitor, 0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN) );
lpMonitorInfo->rcWork = rcWork;
lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
if (lpMonitorInfo->cbSize >= sizeof(MONITORINFOEXW))
strcpyW(((MONITORINFOEXW*)lpMonitorInfo)->szDevice, primary_device_name);
return TRUE;
}
return FALSE;
return USER_Driver->pGetMonitorInfo( hMonitor, lpMonitorInfo );
}
/***********************************************************************
* EnumDisplayMonitors (USER32.@)
*/
BOOL WINAPI EnumDisplayMonitors(
HDC hdcOptionalForPainting,
LPRECT lprcEnumMonitorsThatIntersect,
MONITORENUMPROC lpfnEnumProc,
LPARAM dwData)
BOOL WINAPI EnumDisplayMonitors( HDC hdc, LPRECT rect, MONITORENUMPROC proc, LPARAM lp )
{
RECT rcLimit;
SetRect( &rcLimit, 0, 0, GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN) );
if (!lpfnEnumProc)
return FALSE;
if (hdcOptionalForPainting)
{
RECT rcClip;
POINT ptOrg;
switch (GetClipBox(hdcOptionalForPainting, &rcClip))
{
default:
if (!GetDCOrgEx(hdcOptionalForPainting, &ptOrg))
return FALSE;
OffsetRect(&rcLimit, -ptOrg.x, -ptOrg.y);
if (IntersectRect(&rcLimit, &rcLimit, &rcClip) &&
(!lprcEnumMonitorsThatIntersect ||
IntersectRect(&rcLimit, &rcLimit, lprcEnumMonitorsThatIntersect))) {
break;
}
/* fall through */
case NULLREGION:
return TRUE;
case ERROR:
return FALSE;
}
} else {
if ( lprcEnumMonitorsThatIntersect &&
!IntersectRect(&rcLimit, &rcLimit, lprcEnumMonitorsThatIntersect)) {
return TRUE;
}
}
return lpfnEnumProc(
xPRIMARY_MONITOR,
hdcOptionalForPainting,
&rcLimit,
dwData);
return USER_Driver->pEnumDisplayMonitors( hdc, rect, proc, lp );
}
/***********************************************************************

View File

@ -134,7 +134,9 @@ typedef struct tagUSER_DRIVER {
BOOL (*pSetClipboardData)(UINT, HANDLE16, HANDLE, BOOL); /* Set specified selection data */
/* display modes */
LONG (*pChangeDisplaySettingsEx)(LPCWSTR,LPDEVMODEW,HWND,DWORD,LPVOID);
BOOL (*pEnumDisplayMonitors)(HDC,LPRECT,MONITORENUMPROC,LPARAM);
BOOL (*pEnumDisplaySettingsEx)(LPCWSTR,DWORD,LPDEVMODEW,DWORD);
BOOL (*pGetMonitorInfo)(HMONITOR,MONITORINFO*);
/* windowing functions */
BOOL (*pCreateDesktopWindow)(HWND);
BOOL (*pCreateWindow)(HWND,CREATESTRUCTA*,BOOL);

View File

@ -82,7 +82,9 @@
@ cdecl GetScreenSaveActive() X11DRV_GetScreenSaveActive
@ cdecl SetScreenSaveActive(long) X11DRV_SetScreenSaveActive
@ cdecl ChangeDisplaySettingsEx(ptr ptr long long long) X11DRV_ChangeDisplaySettingsEx
@ cdecl EnumDisplayMonitors(long ptr ptr long) X11DRV_EnumDisplayMonitors
@ cdecl EnumDisplaySettingsEx(ptr long ptr long) X11DRV_EnumDisplaySettingsEx
@ cdecl GetMonitorInfo(long ptr) X11DRV_GetMonitorInfo
@ cdecl AcquireClipboard(long) X11DRV_AcquireClipboard
@ cdecl CountClipboardFormats() X11DRV_CountClipboardFormats
@ cdecl CreateDesktopWindow(long) X11DRV_CreateDesktopWindow

View File

@ -53,6 +53,19 @@ static inline MONITORINFOEXW *get_primary(void)
return &monitors[idx];
}
static inline HMONITOR index_to_monitor( int index )
{
return (HMONITOR)(UINT_PTR)(index + 1);
}
static inline int monitor_to_index( HMONITOR handle )
{
UINT_PTR index = (UINT_PTR)handle;
if (index < 1 || index > nb_monitors) return -1;
return index - 1;
}
#ifdef HAVE_LIBXINERAMA
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
@ -110,8 +123,8 @@ static int query_screens(void)
get_primary()->dwFlags |= MONITORINFOF_PRIMARY;
for (i = 0; i < nb_monitors; i++)
TRACE( "monitor %d: %s%s\n",
i, wine_dbgstr_rect(&monitors[i].rcMonitor),
TRACE( "monitor %p: %s%s\n",
index_to_monitor(i), wine_dbgstr_rect(&monitors[i].rcMonitor),
(monitors[i].dwFlags & MONITORINFOF_PRIMARY) ? " (primary)" : "" );
}
else count = 0;
@ -154,3 +167,62 @@ void xinerama_init(void)
wine_tsx11_unlock();
}
/***********************************************************************
* X11DRV_GetMonitorInfo (X11DRV.@)
*/
BOOL X11DRV_GetMonitorInfo( HMONITOR handle, LPMONITORINFO info )
{
int i = monitor_to_index( handle );
if (i == -1)
{
SetLastError( ERROR_INVALID_HANDLE );
return FALSE;
}
info->rcMonitor = monitors[i].rcMonitor;
info->rcWork = monitors[i].rcWork;
info->dwFlags = monitors[i].dwFlags;
if (info->cbSize >= sizeof(MONITORINFOEXW))
lstrcpyW( ((MONITORINFOEXW *)info)->szDevice, monitors[i].szDevice );
return TRUE;
}
/***********************************************************************
* X11DRV_EnumDisplayMonitors (X11DRV.@)
*/
BOOL X11DRV_EnumDisplayMonitors( HDC hdc, LPRECT rect, MONITORENUMPROC proc, LPARAM lp )
{
int i;
if (hdc)
{
POINT origin;
RECT limit;
if (!GetDCOrgEx( hdc, &origin )) return FALSE;
if (GetClipBox( hdc, &limit ) == ERROR) return FALSE;
if (rect && !IntersectRect( &limit, &limit, rect )) return TRUE;
for (i = 0; i < nb_monitors; i++)
{
RECT monrect = monitors[i].rcMonitor;
OffsetRect( &monrect, -origin.x, -origin.y );
if (IntersectRect( &monrect, &monrect, &limit ))
if (!proc( index_to_monitor(i), hdc, &monrect, lp )) break;
}
}
else
{
for (i = 0; i < nb_monitors; i++)
{
RECT unused;
if (!rect || IntersectRect( &unused, &monitors[i].rcMonitor, rect ))
if (!proc( index_to_monitor(i), 0, &monitors[i].rcMonitor, lp )) break;
}
}
return TRUE;
}