365 lines
12 KiB
C
365 lines
12 KiB
C
|
/**
|
||
|
* This file has no copyright assigned and is placed in the Public Domain.
|
||
|
* This file is part of the w64 mingw-runtime package.
|
||
|
* No warranty is given; refer to the file DISCLAIMER within this package.
|
||
|
*/
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
#ifndef SM_CMONITORS
|
||
|
#define SM_XVIRTUALSCREEN 76
|
||
|
#define SM_YVIRTUALSCREEN 77
|
||
|
#define SM_CXVIRTUALSCREEN 78
|
||
|
#define SM_CYVIRTUALSCREEN 79
|
||
|
#define SM_CMONITORS 80
|
||
|
#define SM_SAMEDISPLAYFORMAT 81
|
||
|
|
||
|
#define MONITOR_DEFAULTTONULL 0x00000000
|
||
|
#define MONITOR_DEFAULTTOPRIMARY 0x00000001
|
||
|
#define MONITOR_DEFAULTTONEAREST 0x00000002
|
||
|
|
||
|
#define MONITORINFOF_PRIMARY 0x00000001
|
||
|
|
||
|
typedef struct tagMONITORINFO {
|
||
|
DWORD cbSize;
|
||
|
RECT rcMonitor;
|
||
|
RECT rcWork;
|
||
|
DWORD dwFlags;
|
||
|
} MONITORINFO,*LPMONITORINFO;
|
||
|
|
||
|
#ifndef CCHDEVICENAME
|
||
|
#define CCHDEVICENAME 32
|
||
|
#endif
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
typedef struct tagMONITORINFOEXA : public tagMONITORINFO {
|
||
|
CHAR szDevice[CCHDEVICENAME];
|
||
|
} MONITORINFOEXA,*LPMONITORINFOEXA;
|
||
|
|
||
|
typedef struct tagMONITORINFOEXW : public tagMONITORINFO {
|
||
|
WCHAR szDevice[CCHDEVICENAME];
|
||
|
} MONITORINFOEXW,*LPMONITORINFOEXW;
|
||
|
#ifdef UNICODE
|
||
|
typedef MONITORINFOEXW MONITORINFOEX;
|
||
|
typedef LPMONITORINFOEXW LPMONITORINFOEX;
|
||
|
#else
|
||
|
typedef MONITORINFOEXA MONITORINFOEX;
|
||
|
typedef LPMONITORINFOEXA LPMONITORINFOEX;
|
||
|
#endif
|
||
|
#else
|
||
|
typedef struct tagMONITORINFOEXA {
|
||
|
MONITORINFO;
|
||
|
CHAR szDevice[CCHDEVICENAME];
|
||
|
} MONITORINFOEXA,*LPMONITORINFOEXA;
|
||
|
|
||
|
typedef struct tagMONITORINFOEXW {
|
||
|
MONITORINFO;
|
||
|
WCHAR szDevice[CCHDEVICENAME];
|
||
|
} MONITORINFOEXW,*LPMONITORINFOEXW;
|
||
|
#ifdef UNICODE
|
||
|
typedef MONITORINFOEXW MONITORINFOEX;
|
||
|
typedef LPMONITORINFOEXW LPMONITORINFOEX;
|
||
|
#else
|
||
|
typedef MONITORINFOEXA MONITORINFOEX;
|
||
|
typedef LPMONITORINFOEXA LPMONITORINFOEX;
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
typedef WINBOOL (CALLBACK *MONITORENUMPROC)(HMONITOR,HDC,LPRECT,LPARAM);
|
||
|
|
||
|
#ifndef DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
|
||
|
typedef struct _DISPLAY_DEVICEA {
|
||
|
DWORD cb;
|
||
|
CHAR DeviceName[32];
|
||
|
CHAR DeviceString[128];
|
||
|
DWORD StateFlags;
|
||
|
CHAR DeviceID[128];
|
||
|
CHAR DeviceKey[128];
|
||
|
} DISPLAY_DEVICEA,*PDISPLAY_DEVICEA,*LPDISPLAY_DEVICEA;
|
||
|
|
||
|
typedef struct _DISPLAY_DEVICEW {
|
||
|
DWORD cb;
|
||
|
WCHAR DeviceName[32];
|
||
|
WCHAR DeviceString[128];
|
||
|
DWORD StateFlags;
|
||
|
WCHAR DeviceID[128];
|
||
|
WCHAR DeviceKey[128];
|
||
|
} DISPLAY_DEVICEW,*PDISPLAY_DEVICEW,*LPDISPLAY_DEVICEW;
|
||
|
#ifdef UNICODE
|
||
|
typedef DISPLAY_DEVICEW DISPLAY_DEVICE;
|
||
|
typedef PDISPLAY_DEVICEW PDISPLAY_DEVICE;
|
||
|
typedef LPDISPLAY_DEVICEW LPDISPLAY_DEVICE;
|
||
|
#else
|
||
|
typedef DISPLAY_DEVICEA DISPLAY_DEVICE;
|
||
|
typedef PDISPLAY_DEVICEA PDISPLAY_DEVICE;
|
||
|
typedef LPDISPLAY_DEVICEA LPDISPLAY_DEVICE;
|
||
|
#endif
|
||
|
|
||
|
#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
|
||
|
#define DISPLAY_DEVICE_MULTI_DRIVER 0x00000002
|
||
|
#define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004
|
||
|
#define DISPLAY_DEVICE_MIRRORING_DRIVER 0x00000008
|
||
|
#define DISPLAY_DEVICE_VGA_COMPATIBLE 0x00000010
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#undef GetMonitorInfo
|
||
|
#undef GetSystemMetrics
|
||
|
#undef MonitorFromWindow
|
||
|
#undef MonitorFromRect
|
||
|
#undef MonitorFromPoint
|
||
|
#undef EnumDisplayMonitors
|
||
|
#undef EnumDisplayDevices
|
||
|
|
||
|
#ifdef COMPILE_MULTIMON_STUBS
|
||
|
|
||
|
#ifndef MULTIMON_FNS_DEFINED
|
||
|
int (WINAPI *g_pfnGetSystemMetrics)(int) = NULL;
|
||
|
HMONITOR (WINAPI *g_pfnMonitorFromWindow)(HWND,DWORD) = NULL;
|
||
|
HMONITOR (WINAPI *g_pfnMonitorFromRect)(LPCRECT,DWORD) = NULL;
|
||
|
HMONITOR (WINAPI *g_pfnMonitorFromPoint)(POINT,DWORD) = NULL;
|
||
|
WINBOOL (WINAPI *g_pfnGetMonitorInfo)(HMONITOR,LPMONITORINFO) = NULL;
|
||
|
WINBOOL (WINAPI *g_pfnEnumDisplayMonitors)(HDC,LPCRECT,MONITORENUMPROC,LPARAM) = NULL;
|
||
|
WINBOOL (WINAPI *g_pfnEnumDisplayDevices)(PVOID,DWORD,PDISPLAY_DEVICE,DWORD) = NULL;
|
||
|
WINBOOL g_fMultiMonInitDone = FALSE;
|
||
|
WINBOOL g_fMultimonPlatformNT = FALSE;
|
||
|
#endif
|
||
|
|
||
|
WINBOOL IsPlatformNT() {
|
||
|
OSVERSIONINFOA osvi = {0};
|
||
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||
|
GetVersionExA((OSVERSIONINFOA*)&osvi);
|
||
|
return (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId);
|
||
|
}
|
||
|
|
||
|
WINBOOL InitMultipleMonitorStubs(void) {
|
||
|
HMODULE hUser32;
|
||
|
if(g_fMultiMonInitDone) return g_pfnGetMonitorInfo!=NULL;
|
||
|
g_fMultimonPlatformNT = IsPlatformNT();
|
||
|
hUser32 = GetModuleHandle(TEXT("USER32"));
|
||
|
if(hUser32 &&
|
||
|
(*(FARPROC*)&g_pfnGetSystemMetrics = GetProcAddress(hUser32,"GetSystemMetrics"))!=NULL &&
|
||
|
(*(FARPROC*)&g_pfnMonitorFromWindow = GetProcAddress(hUser32,"MonitorFromWindow"))!=NULL &&
|
||
|
(*(FARPROC*)&g_pfnMonitorFromRect = GetProcAddress(hUser32,"MonitorFromRect"))!=NULL &&
|
||
|
(*(FARPROC*)&g_pfnMonitorFromPoint = GetProcAddress(hUser32,"MonitorFromPoint"))!=NULL &&
|
||
|
(*(FARPROC*)&g_pfnEnumDisplayMonitors = GetProcAddress(hUser32,"EnumDisplayMonitors"))!=NULL &&
|
||
|
#ifdef UNICODE
|
||
|
(*(FARPROC*)&g_pfnEnumDisplayDevices = GetProcAddress(hUser32,"EnumDisplayDevicesW"))!=NULL &&
|
||
|
(*(FARPROC*)&g_pfnGetMonitorInfo = g_fMultimonPlatformNT ? GetProcAddress(hUser32,"GetMonitorInfoW") :
|
||
|
GetProcAddress(hUser32,"GetMonitorInfoA"))!=NULL
|
||
|
#else
|
||
|
(*(FARPROC*)&g_pfnGetMonitorInfo = GetProcAddress(hUser32,"GetMonitorInfoA"))!=NULL &&
|
||
|
(*(FARPROC*)&g_pfnEnumDisplayDevices = GetProcAddress(hUser32,"EnumDisplayDevicesA"))!=NULL
|
||
|
#endif
|
||
|
) {
|
||
|
g_fMultiMonInitDone = TRUE;
|
||
|
return TRUE;
|
||
|
} else {
|
||
|
g_pfnGetSystemMetrics = NULL;
|
||
|
g_pfnMonitorFromWindow = NULL;
|
||
|
g_pfnMonitorFromRect = NULL;
|
||
|
g_pfnMonitorFromPoint = NULL;
|
||
|
g_pfnGetMonitorInfo = NULL;
|
||
|
g_pfnEnumDisplayMonitors = NULL;
|
||
|
g_pfnEnumDisplayDevices = NULL;
|
||
|
g_fMultiMonInitDone = TRUE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int WINAPI xGetSystemMetrics(int nIndex) {
|
||
|
if(InitMultipleMonitorStubs()) return g_pfnGetSystemMetrics(nIndex);
|
||
|
switch(nIndex) {
|
||
|
case SM_CMONITORS:
|
||
|
case SM_SAMEDISPLAYFORMAT:
|
||
|
return 1;
|
||
|
case SM_XVIRTUALSCREEN:
|
||
|
case SM_YVIRTUALSCREEN:
|
||
|
return 0;
|
||
|
case SM_CXVIRTUALSCREEN:
|
||
|
nIndex = SM_CXSCREEN;
|
||
|
break;
|
||
|
case SM_CYVIRTUALSCREEN:
|
||
|
nIndex = SM_CYSCREEN;
|
||
|
break;
|
||
|
}
|
||
|
return GetSystemMetrics(nIndex);
|
||
|
}
|
||
|
|
||
|
#define xPRIMARY_MONITOR ((HMONITOR)0x12340042)
|
||
|
|
||
|
HMONITOR WINAPI xMonitorFromPoint(POINT ptScreenCoords,DWORD dwFlags) {
|
||
|
if(InitMultipleMonitorStubs()) return g_pfnMonitorFromPoint(ptScreenCoords,dwFlags);
|
||
|
if((dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
|
||
|
((ptScreenCoords.x >= 0) &&
|
||
|
(ptScreenCoords.x < GetSystemMetrics(SM_CXSCREEN)) &&
|
||
|
(ptScreenCoords.y >= 0) &&
|
||
|
(ptScreenCoords.y < GetSystemMetrics(SM_CYSCREEN))))
|
||
|
{
|
||
|
return xPRIMARY_MONITOR;
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
HMONITOR WINAPI xMonitorFromRect(LPCRECT lprcScreenCoords,DWORD dwFlags)
|
||
|
{
|
||
|
if(InitMultipleMonitorStubs()) return g_pfnMonitorFromRect(lprcScreenCoords,dwFlags);
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
HMONITOR WINAPI xMonitorFromWindow(HWND hWnd,DWORD dwFlags) {
|
||
|
WINDOWPLACEMENT wp;
|
||
|
if(InitMultipleMonitorStubs()) return g_pfnMonitorFromWindow(hWnd,dwFlags);
|
||
|
if(dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) return xPRIMARY_MONITOR;
|
||
|
if(IsIconic(hWnd) ? GetWindowPlacement(hWnd,&wp) : GetWindowRect(hWnd,&wp.rcNormalPosition)) return xMonitorFromRect(&wp.rcNormalPosition,dwFlags);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
WINBOOL WINAPI xGetMonitorInfo(HMONITOR hMonitor,LPMONITORINFO lpMonitorInfo) {
|
||
|
RECT rcWork;
|
||
|
if(InitMultipleMonitorStubs()) {
|
||
|
WINBOOL f = g_pfnGetMonitorInfo(hMonitor,lpMonitorInfo);
|
||
|
#ifdef UNICODE
|
||
|
if(f && !g_fMultimonPlatformNT && (lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX))) {
|
||
|
MultiByteToWideChar(CP_ACP,0,(LPSTR)((MONITORINFOEX*)lpMonitorInfo)->szDevice,-1,((MONITORINFOEX*)lpMonitorInfo)->szDevice,(sizeof(((MONITORINFOEX*)lpMonitorInfo)->szDevice)/sizeof(TCHAR)));
|
||
|
}
|
||
|
#endif
|
||
|
return f;
|
||
|
}
|
||
|
if((hMonitor==xPRIMARY_MONITOR) &&
|
||
|
lpMonitorInfo &&
|
||
|
(lpMonitorInfo->cbSize >= sizeof(MONITORINFO)) &&
|
||
|
SystemParametersInfoA(SPI_GETWORKAREA,0,&rcWork,0))
|
||
|
{
|
||
|
lpMonitorInfo->rcMonitor.left = 0;
|
||
|
lpMonitorInfo->rcMonitor.top = 0;
|
||
|
lpMonitorInfo->rcMonitor.right = GetSystemMetrics(SM_CXSCREEN);
|
||
|
lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics(SM_CYSCREEN);
|
||
|
lpMonitorInfo->rcWork = rcWork;
|
||
|
lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
|
||
|
if(lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX)) {
|
||
|
#ifdef UNICODE
|
||
|
MultiByteToWideChar(CP_ACP,0,"DISPLAY",-1,((MONITORINFOEX*)lpMonitorInfo)->szDevice,(sizeof(((MONITORINFOEX*)lpMonitorInfo)->szDevice)/sizeof(TCHAR)));
|
||
|
#else
|
||
|
lstrcpyn(((MONITORINFOEX*)lpMonitorInfo)->szDevice,TEXT("DISPLAY"),(sizeof(((MONITORINFOEX*)lpMonitorInfo)->szDevice)/sizeof(TCHAR)));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
WINBOOL WINAPI
|
||
|
xEnumDisplayMonitors(HDC hdcOptionalForPainting,LPCRECT lprcEnumMonitorsThatIntersect,MONITORENUMPROC lpfnEnumProc,LPARAM dwData)
|
||
|
{
|
||
|
RECT rcLimit;
|
||
|
|
||
|
if(InitMultipleMonitorStubs()) {
|
||
|
return g_pfnEnumDisplayMonitors(hdcOptionalForPainting,lprcEnumMonitorsThatIntersect,lpfnEnumProc,dwData);
|
||
|
}
|
||
|
|
||
|
if(!lpfnEnumProc)
|
||
|
return FALSE;
|
||
|
|
||
|
rcLimit.left = 0;
|
||
|
rcLimit.top = 0;
|
||
|
rcLimit.right = GetSystemMetrics(SM_CXSCREEN);
|
||
|
rcLimit.bottom = GetSystemMetrics(SM_CYSCREEN);
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
case NULLREGION:
|
||
|
return TRUE;
|
||
|
case ERROR:
|
||
|
return FALSE;
|
||
|
}
|
||
|
} else {
|
||
|
if(lprcEnumMonitorsThatIntersect &&
|
||
|
!IntersectRect(&rcLimit,&rcLimit,lprcEnumMonitorsThatIntersect)) {
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return lpfnEnumProc(xPRIMARY_MONITOR,hdcOptionalForPainting,&rcLimit,dwData);
|
||
|
}
|
||
|
|
||
|
WINBOOL WINAPI
|
||
|
xEnumDisplayDevices(PVOID Unused,DWORD iDevNum,PDISPLAY_DEVICE lpDisplayDevice,DWORD dwFlags)
|
||
|
{
|
||
|
if(InitMultipleMonitorStubs())
|
||
|
return g_pfnEnumDisplayDevices(Unused,iDevNum,lpDisplayDevice,dwFlags);
|
||
|
|
||
|
if(Unused!=NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
if(iDevNum!=0)
|
||
|
return FALSE;
|
||
|
|
||
|
if(!lpDisplayDevice || lpDisplayDevice->cb < sizeof(DISPLAY_DEVICE))
|
||
|
return FALSE;
|
||
|
|
||
|
#ifdef UNICODE
|
||
|
MultiByteToWideChar(CP_ACP,0,"DISPLAY",-1,lpDisplayDevice->DeviceName,(sizeof(lpDisplayDevice->DeviceName)/sizeof(TCHAR)));
|
||
|
MultiByteToWideChar(CP_ACP,0,"DISPLAY",-1,lpDisplayDevice->DeviceString,(sizeof(lpDisplayDevice->DeviceString)/sizeof(TCHAR)));
|
||
|
#else
|
||
|
lstrcpyn((LPTSTR)lpDisplayDevice->DeviceName,TEXT("DISPLAY"),(sizeof(lpDisplayDevice->DeviceName)/sizeof(TCHAR)));
|
||
|
lstrcpyn((LPTSTR)lpDisplayDevice->DeviceString,TEXT("DISPLAY"),(sizeof(lpDisplayDevice->DeviceString)/sizeof(TCHAR)));
|
||
|
#endif
|
||
|
lpDisplayDevice->StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
#undef xPRIMARY_MONITOR
|
||
|
#undef COMPILE_MULTIMON_STUBS
|
||
|
#else
|
||
|
|
||
|
extern int WINAPI xGetSystemMetrics(int);
|
||
|
extern HMONITOR WINAPI xMonitorFromWindow(HWND,DWORD);
|
||
|
extern HMONITOR WINAPI xMonitorFromRect(LPCRECT,DWORD);
|
||
|
extern HMONITOR WINAPI xMonitorFromPoint(POINT,DWORD);
|
||
|
extern WINBOOL WINAPI xGetMonitorInfo(HMONITOR,LPMONITORINFO);
|
||
|
extern WINBOOL WINAPI xEnumDisplayMonitors(HDC,LPCRECT,MONITORENUMPROC,LPARAM);
|
||
|
extern WINBOOL WINAPI xEnumDisplayDevices(PVOID,DWORD,PDISPLAY_DEVICE,DWORD);
|
||
|
#endif
|
||
|
|
||
|
#define GetSystemMetrics xGetSystemMetrics
|
||
|
#define MonitorFromWindow xMonitorFromWindow
|
||
|
#define MonitorFromRect xMonitorFromRect
|
||
|
#define MonitorFromPoint xMonitorFromPoint
|
||
|
#define GetMonitorInfo xGetMonitorInfo
|
||
|
#define EnumDisplayMonitors xEnumDisplayMonitors
|
||
|
#define EnumDisplayDevices xEnumDisplayDevices
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}
|
||
|
#endif
|