1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6
7#include <_mingw_unicode.h>
8
9#ifdef __cplusplus
10extern "C" {
11#endif
12
13#ifndef SM_CMONITORS
14#define SM_XVIRTUALSCREEN 76
15#define SM_YVIRTUALSCREEN 77
16#define SM_CXVIRTUALSCREEN 78
17#define SM_CYVIRTUALSCREEN 79
18#define SM_CMONITORS 80
19#define SM_SAMEDISPLAYFORMAT 81
20
21#define MONITOR_DEFAULTTONULL 0x00000000
22#define MONITOR_DEFAULTTOPRIMARY 0x00000001
23#define MONITOR_DEFAULTTONEAREST 0x00000002
24
25#define MONITORINFOF_PRIMARY 0x00000001
26
27  typedef struct tagMONITORINFO {
28    DWORD cbSize;
29    RECT rcMonitor;
30    RECT rcWork;
31    DWORD dwFlags;
32  } MONITORINFO,*LPMONITORINFO;
33
34#ifndef CCHDEVICENAME
35#define CCHDEVICENAME 32
36#endif
37
38#ifdef __cplusplus
39  typedef struct tagMONITORINFOEXA : public tagMONITORINFO {
40    CHAR szDevice[CCHDEVICENAME];
41  } MONITORINFOEXA,*LPMONITORINFOEXA;
42
43  typedef struct tagMONITORINFOEXW : public tagMONITORINFO {
44    WCHAR szDevice[CCHDEVICENAME];
45  } MONITORINFOEXW,*LPMONITORINFOEXW;
46
47  __MINGW_TYPEDEF_AW(MONITORINFOEX)
48  __MINGW_TYPEDEF_AW(LPMONITORINFOEX)
49#else
50  typedef struct tagMONITORINFOEXA {
51    MONITORINFO;
52    CHAR szDevice[CCHDEVICENAME];
53  } MONITORINFOEXA,*LPMONITORINFOEXA;
54
55  typedef struct tagMONITORINFOEXW {
56    MONITORINFO;
57    WCHAR szDevice[CCHDEVICENAME];
58  } MONITORINFOEXW,*LPMONITORINFOEXW;
59  __MINGW_TYPEDEF_AW(MONITORINFOEX)
60  __MINGW_TYPEDEF_AW(LPMONITORINFOEX)
61#endif
62
63  typedef WINBOOL (CALLBACK *MONITORENUMPROC)(HMONITOR,HDC,LPRECT,LPARAM);
64
65#ifndef DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
66  typedef struct _DISPLAY_DEVICEA {
67    DWORD cb;
68    CHAR DeviceName[32];
69    CHAR DeviceString[128];
70    DWORD StateFlags;
71    CHAR DeviceID[128];
72    CHAR DeviceKey[128];
73  } DISPLAY_DEVICEA,*PDISPLAY_DEVICEA,*LPDISPLAY_DEVICEA;
74
75  typedef struct _DISPLAY_DEVICEW {
76    DWORD cb;
77    WCHAR DeviceName[32];
78    WCHAR DeviceString[128];
79    DWORD StateFlags;
80    WCHAR DeviceID[128];
81    WCHAR DeviceKey[128];
82  } DISPLAY_DEVICEW,*PDISPLAY_DEVICEW,*LPDISPLAY_DEVICEW;
83
84  __MINGW_TYPEDEF_AW(DISPLAY_DEVICE)
85  __MINGW_TYPEDEF_AW(PDISPLAY_DEVICE)
86  __MINGW_TYPEDEF_AW(LPDISPLAY_DEVICE)
87
88#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
89#define DISPLAY_DEVICE_MULTI_DRIVER 0x00000002
90#define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004
91#define DISPLAY_DEVICE_MIRRORING_DRIVER 0x00000008
92#define DISPLAY_DEVICE_VGA_COMPATIBLE 0x00000010
93#endif
94#endif
95
96#undef GetMonitorInfo
97#undef GetSystemMetrics
98#undef MonitorFromWindow
99#undef MonitorFromRect
100#undef MonitorFromPoint
101#undef EnumDisplayMonitors
102#undef EnumDisplayDevices
103
104#ifdef COMPILE_MULTIMON_STUBS
105
106#ifndef MULTIMON_FNS_DEFINED
107  int (WINAPI *g_pfnGetSystemMetrics)(int) = NULL;
108  HMONITOR (WINAPI *g_pfnMonitorFromWindow)(HWND,DWORD) = NULL;
109  HMONITOR (WINAPI *g_pfnMonitorFromRect)(LPCRECT,DWORD) = NULL;
110  HMONITOR (WINAPI *g_pfnMonitorFromPoint)(POINT,DWORD) = NULL;
111  WINBOOL (WINAPI *g_pfnGetMonitorInfo)(HMONITOR,LPMONITORINFO) = NULL;
112  WINBOOL (WINAPI *g_pfnEnumDisplayMonitors)(HDC,LPCRECT,MONITORENUMPROC,LPARAM) = NULL;
113  WINBOOL (WINAPI *g_pfnEnumDisplayDevices)(PVOID,DWORD,PDISPLAY_DEVICE,DWORD) = NULL;
114  WINBOOL g_fMultiMonInitDone = FALSE;
115  WINBOOL g_fMultimonPlatformNT = FALSE;
116#endif
117
118  WINBOOL IsPlatformNT() {
119    OSVERSIONINFOA osvi = {0};
120    osvi.dwOSVersionInfoSize = sizeof(osvi);
121    GetVersionExA((OSVERSIONINFOA*)&osvi);
122    return (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId);
123  }
124
125  WINBOOL InitMultipleMonitorStubs(void) {
126    HMODULE hUser32;
127    if(g_fMultiMonInitDone) return g_pfnGetMonitorInfo!=NULL;
128    g_fMultimonPlatformNT = IsPlatformNT();
129    hUser32 = GetModuleHandle(TEXT("USER32"));
130    if(hUser32 &&
131      (*(FARPROC*)&g_pfnGetSystemMetrics = GetProcAddress(hUser32,"GetSystemMetrics"))!=NULL &&
132      (*(FARPROC*)&g_pfnMonitorFromWindow = GetProcAddress(hUser32,"MonitorFromWindow"))!=NULL &&
133      (*(FARPROC*)&g_pfnMonitorFromRect = GetProcAddress(hUser32,"MonitorFromRect"))!=NULL &&
134      (*(FARPROC*)&g_pfnMonitorFromPoint = GetProcAddress(hUser32,"MonitorFromPoint"))!=NULL &&
135      (*(FARPROC*)&g_pfnEnumDisplayMonitors = GetProcAddress(hUser32,"EnumDisplayMonitors"))!=NULL &&
136      (*(FARPROC*)&g_pfnEnumDisplayDevices = GetProcAddress(hUser32,"EnumDisplayDevices" __MINGW_PROCNAMEEXT_AW))!=NULL &&
137      (*(FARPROC*)&g_pfnGetMonitorInfo = g_fMultimonPlatformNT ? GetProcAddress(hUser32,"GetMonitorInfo" __MINGW_PROCNAMEEXT_AW) :
138      GetProcAddress(hUser32,"GetMonitorInfoA"))!=NULL
139      ) {
140	g_fMultiMonInitDone = TRUE;
141	return TRUE;
142    } else {
143      g_pfnGetSystemMetrics = NULL;
144      g_pfnMonitorFromWindow = NULL;
145      g_pfnMonitorFromRect = NULL;
146      g_pfnMonitorFromPoint = NULL;
147      g_pfnGetMonitorInfo = NULL;
148      g_pfnEnumDisplayMonitors = NULL;
149      g_pfnEnumDisplayDevices = NULL;
150      g_fMultiMonInitDone = TRUE;
151      return FALSE;
152    }
153  }
154
155  int WINAPI xGetSystemMetrics(int nIndex) {
156    if(InitMultipleMonitorStubs()) return g_pfnGetSystemMetrics(nIndex);
157    switch(nIndex) {
158	case SM_CMONITORS:
159	case SM_SAMEDISPLAYFORMAT:
160	  return 1;
161	case SM_XVIRTUALSCREEN:
162	case SM_YVIRTUALSCREEN:
163	  return 0;
164	case SM_CXVIRTUALSCREEN:
165	  nIndex = SM_CXSCREEN;
166	  break;
167	case SM_CYVIRTUALSCREEN:
168	  nIndex = SM_CYSCREEN;
169	  break;
170    }
171    return GetSystemMetrics(nIndex);
172  }
173
174#define xPRIMARY_MONITOR ((HMONITOR)0x12340042)
175
176  HMONITOR WINAPI xMonitorFromPoint(POINT ptScreenCoords,DWORD dwFlags) {
177    if(InitMultipleMonitorStubs()) return g_pfnMonitorFromPoint(ptScreenCoords,dwFlags);
178    if((dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
179      ((ptScreenCoords.x >= 0) &&
180      (ptScreenCoords.x < GetSystemMetrics(SM_CXSCREEN)) &&
181      (ptScreenCoords.y >= 0) &&
182      (ptScreenCoords.y < GetSystemMetrics(SM_CYSCREEN))))
183    {
184      return xPRIMARY_MONITOR;
185    }
186    return NULL;
187  }
188
189  HMONITOR WINAPI xMonitorFromRect(LPCRECT lprcScreenCoords,DWORD dwFlags)
190  {
191    if(InitMultipleMonitorStubs()) return g_pfnMonitorFromRect(lprcScreenCoords,dwFlags);
192    if((dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
193      ((lprcScreenCoords->right > 0) &&
194      (lprcScreenCoords->bottom > 0) &&
195      (lprcScreenCoords->left < GetSystemMetrics(SM_CXSCREEN)) &&
196      (lprcScreenCoords->top < GetSystemMetrics(SM_CYSCREEN))))
197    {
198      return xPRIMARY_MONITOR;
199    }
200    return NULL;
201  }
202
203  HMONITOR WINAPI xMonitorFromWindow(HWND hWnd,DWORD dwFlags) {
204    WINDOWPLACEMENT wp;
205    if(InitMultipleMonitorStubs()) return g_pfnMonitorFromWindow(hWnd,dwFlags);
206    if(dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) return xPRIMARY_MONITOR;
207    if(IsIconic(hWnd) ? GetWindowPlacement(hWnd,&wp) : GetWindowRect(hWnd,&wp.rcNormalPosition)) return xMonitorFromRect(&wp.rcNormalPosition,dwFlags);
208    return NULL;
209  }
210
211  WINBOOL WINAPI xGetMonitorInfo(HMONITOR hMonitor,LPMONITORINFO lpMonitorInfo) {
212    RECT rcWork;
213    if(InitMultipleMonitorStubs()) {
214      WINBOOL f = g_pfnGetMonitorInfo(hMonitor,lpMonitorInfo);
215#if defined(UNICODE)
216      if(f && !g_fMultimonPlatformNT && (lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX))) {
217	MultiByteToWideChar(CP_ACP,0,(LPSTR)((MONITORINFOEX*)lpMonitorInfo)->szDevice,-1,((MONITORINFOEX*)lpMonitorInfo)->szDevice,(sizeof(((MONITORINFOEX*)lpMonitorInfo)->szDevice)/sizeof(TCHAR)));
218      }
219#endif
220      return f;
221    }
222    if((hMonitor==xPRIMARY_MONITOR) &&
223      lpMonitorInfo &&
224      (lpMonitorInfo->cbSize >= sizeof(MONITORINFO)) &&
225      SystemParametersInfoA(SPI_GETWORKAREA,0,&rcWork,0))
226    {
227      lpMonitorInfo->rcMonitor.left = 0;
228      lpMonitorInfo->rcMonitor.top = 0;
229      lpMonitorInfo->rcMonitor.right = GetSystemMetrics(SM_CXSCREEN);
230      lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics(SM_CYSCREEN);
231      lpMonitorInfo->rcWork = rcWork;
232      lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
233      if(lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX)) {
234#if defined(UNICODE)
235	MultiByteToWideChar(CP_ACP,0,"DISPLAY",-1,((MONITORINFOEX*)lpMonitorInfo)->szDevice,(sizeof(((MONITORINFOEX*)lpMonitorInfo)->szDevice)/sizeof(TCHAR)));
236#else
237	lstrcpyn(((MONITORINFOEX*)lpMonitorInfo)->szDevice,TEXT("DISPLAY"),(sizeof(((MONITORINFOEX*)lpMonitorInfo)->szDevice)/sizeof(TCHAR)));
238#endif
239      }
240
241      return TRUE;
242    }
243
244    return FALSE;
245  }
246
247  WINBOOL WINAPI
248    xEnumDisplayMonitors(HDC hdcOptionalForPainting,LPCRECT lprcEnumMonitorsThatIntersect,MONITORENUMPROC lpfnEnumProc,LPARAM dwData)
249  {
250    RECT rcLimit;
251
252    if(InitMultipleMonitorStubs()) {
253      return g_pfnEnumDisplayMonitors(hdcOptionalForPainting,lprcEnumMonitorsThatIntersect,lpfnEnumProc,dwData);
254    }
255
256    if(!lpfnEnumProc)
257      return FALSE;
258
259    rcLimit.left = 0;
260    rcLimit.top = 0;
261    rcLimit.right = GetSystemMetrics(SM_CXSCREEN);
262    rcLimit.bottom = GetSystemMetrics(SM_CYSCREEN);
263
264    if(hdcOptionalForPainting)
265    {
266      RECT rcClip;
267      POINT ptOrg;
268
269      switch (GetClipBox(hdcOptionalForPainting,&rcClip))
270      {
271      default:
272	if(!GetDCOrgEx(hdcOptionalForPainting,&ptOrg))
273	  return FALSE;
274
275	OffsetRect(&rcLimit,-ptOrg.x,-ptOrg.y);
276	if(IntersectRect(&rcLimit,&rcLimit,&rcClip) &&
277	  (!lprcEnumMonitorsThatIntersect ||
278	  IntersectRect(&rcLimit,&rcLimit,lprcEnumMonitorsThatIntersect))) {
279
280	    break;
281	}
282
283      case NULLREGION:
284	return TRUE;
285      case ERROR:
286	return FALSE;
287      }
288    } else {
289      if(lprcEnumMonitorsThatIntersect &&
290	!IntersectRect(&rcLimit,&rcLimit,lprcEnumMonitorsThatIntersect)) {
291
292	  return TRUE;
293      }
294    }
295
296    return lpfnEnumProc(xPRIMARY_MONITOR,hdcOptionalForPainting,&rcLimit,dwData);
297  }
298
299  WINBOOL WINAPI
300    xEnumDisplayDevices(PVOID Unused,DWORD iDevNum,PDISPLAY_DEVICE lpDisplayDevice,DWORD dwFlags)
301  {
302    if(InitMultipleMonitorStubs())
303      return g_pfnEnumDisplayDevices(Unused,iDevNum,lpDisplayDevice,dwFlags);
304
305    if(Unused!=NULL)
306      return FALSE;
307
308    if(iDevNum!=0)
309      return FALSE;
310
311    if(!lpDisplayDevice || lpDisplayDevice->cb < sizeof(DISPLAY_DEVICE))
312      return FALSE;
313
314#if defined(UNICODE)
315    MultiByteToWideChar(CP_ACP,0,"DISPLAY",-1,lpDisplayDevice->DeviceName,(sizeof(lpDisplayDevice->DeviceName)/sizeof(TCHAR)));
316    MultiByteToWideChar(CP_ACP,0,"DISPLAY",-1,lpDisplayDevice->DeviceString,(sizeof(lpDisplayDevice->DeviceString)/sizeof(TCHAR)));
317#else
318    lstrcpyn((LPTSTR)lpDisplayDevice->DeviceName,TEXT("DISPLAY"),(sizeof(lpDisplayDevice->DeviceName)/sizeof(TCHAR)));
319    lstrcpyn((LPTSTR)lpDisplayDevice->DeviceString,TEXT("DISPLAY"),(sizeof(lpDisplayDevice->DeviceString)/sizeof(TCHAR)));
320#endif
321    lpDisplayDevice->StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE;
322    return TRUE;
323  }
324
325#undef xPRIMARY_MONITOR
326#undef COMPILE_MULTIMON_STUBS
327#else
328
329  extern int WINAPI xGetSystemMetrics(int);
330  extern HMONITOR WINAPI xMonitorFromWindow(HWND,DWORD);
331  extern HMONITOR WINAPI xMonitorFromRect(LPCRECT,DWORD);
332  extern HMONITOR WINAPI xMonitorFromPoint(POINT,DWORD);
333  extern WINBOOL WINAPI xGetMonitorInfo(HMONITOR,LPMONITORINFO);
334  extern WINBOOL WINAPI xEnumDisplayMonitors(HDC,LPCRECT,MONITORENUMPROC,LPARAM);
335  extern WINBOOL WINAPI xEnumDisplayDevices(PVOID,DWORD,PDISPLAY_DEVICE,DWORD);
336#endif
337
338#define GetSystemMetrics xGetSystemMetrics
339#define MonitorFromWindow xMonitorFromWindow
340#define MonitorFromRect xMonitorFromRect
341#define MonitorFromPoint xMonitorFromPoint
342#define GetMonitorInfo xGetMonitorInfo
343#define EnumDisplayMonitors xEnumDisplayMonitors
344#define EnumDisplayDevices xEnumDisplayDevices
345
346#ifdef __cplusplus
347}
348#endif
349