Adding patch_seam q3map2 regression test. Probably not fixable, but good to
[xonotic/netradiant.git] / libs / multimon.h
1 #ifndef __MULTIMON_H
2 #define __MULTIMON_H
3
4 #ifdef _WIN32
5
6 //=============================================================================
7 //
8 // MULTIMON
9 // stub module that "stubs" multiple monitor APIs on pre-Memphis Win32 OSes
10 //
11 // By using this header your code will work unchanged on Win95,
12 // you will get back correct values from GetSystemMetrics() for new metrics
13 // and the new APIs will act like only one display is present.
14 //
15 // exactly one source must include this with COMPILE_MULTIMON_STUBS defined
16 //
17 //=============================================================================
18
19 #ifdef __cplusplus
20 extern "C" {            /* Assume C declarations for C++ */
21 #endif  /* __cplusplus */
22
23 //
24 // if we are building on Win95/NT4 headers we need to declare this stuff ourselves
25 //
26 #ifndef SM_CMONITORS
27
28 #define SM_XVIRTUALSCREEN                   76
29 #define SM_YVIRTUALSCREEN                   77
30 #define SM_CXVIRTUALSCREEN                  78
31 #define SM_CYVIRTUALSCREEN                  79
32 #define SM_CMONITORS                        80
33 #define SM_SAMEDISPLAYFORMAT                81
34
35 DECLARE_HANDLE(HMONITOR);
36
37 #define MONITOR_DEFAULTTONULL               0x00000000
38 #define MONITOR_DEFAULTTOPRIMARY            0x00000001
39 #define MONITOR_DEFAULTTONEAREST            0x00000002
40
41 #define MONITORINFOF_PRIMARY                0x00000001
42
43 typedef struct tagMONITORINFO
44 {
45   DWORD cbSize;
46   RECT  rcMonitor;
47   RECT  rcWork;
48   DWORD dwFlags;
49 } MONITORINFO, *LPMONITORINFO;
50
51 #define CCHDEVICENAME 32
52
53 #ifdef __cplusplus
54 typedef struct tagMONITORINFOEX : public tagMONITORINFO
55 {
56   TCHAR       szDevice[CCHDEVICENAME];
57 } MONITORINFOEX, *LPMONITORINFOEX;
58 #else
59 typedef struct
60 {
61   MONITORINFO;
62   TCHAR       szDevice[CCHDEVICENAME];
63 } MONITORINFOEX, *LPMONITORINFOEX;
64 #endif
65
66 typedef BOOL (CALLBACK* MONITORENUMPROC)(HMONITOR, HDC, LPRECT, LPARAM);
67
68 #endif // SM_CMONITORS
69
70 #ifndef DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
71
72 typedef struct {
73   DWORD cb;
74   CHAR  DeviceName[32];
75   CHAR  DeviceString[128];
76   DWORD StateFlags;
77 } DISPLAY_DEVICE;
78
79 #define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP  0x00000001
80 #define DISPLAY_DEVICE_MULTI_DRIVER         0x00000002
81 #define DISPLAY_DEVICE_PRIMARY_DEVICE       0x00000004
82 #define DISPLAY_DEVICE_MIRRORING_DRIVER     0x00000008
83
84 #endif
85 #define DISPLAY_DEVICE_VGA                  0x00000010
86
87 #ifndef ENUM_CURRENT_SETTINGS
88 #define ENUM_CURRENT_SETTINGS               ((DWORD)-1)
89 #define ENUM_REGISTRY_SETTINGS              ((DWORD)-2)
90 #endif
91
92 #undef GetMonitorInfo
93 #undef GetSystemMetrics
94 #undef MonitorFromWindow
95 #undef MonitorFromRect
96 #undef MonitorFromPoint
97 #undef EnumDisplayMonitors
98 #undef EnumDisplayDevices
99
100 //
101 // define this to compile the stubs
102 // otherwise you get the declarations
103 //
104 #ifdef COMPILE_MULTIMON_STUBS
105
106   //---------------------------------------------------------------------------
107   //
108   // Implement the API stubs.
109   //
110   //---------------------------------------------------------------------------
111
112   int       (WINAPI* g_pfnGetSystemMetrics)(int);
113   HMONITOR  (WINAPI* g_pfnMonitorFromWindow)(HWND, BOOL);
114   HMONITOR  (WINAPI* g_pfnMonitorFromRect)(LPCRECT, BOOL);
115   HMONITOR  (WINAPI* g_pfnMonitorFromPoint)(POINT, BOOL);
116   BOOL      (WINAPI* g_pfnGetMonitorInfo)(HMONITOR, LPMONITORINFO);
117   BOOL      (WINAPI* g_pfnEnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
118   BOOL      (WINAPI *g_pfnEnumDisplayDevices)(LPVOID, int, DISPLAY_DEVICE *, DWORD);
119
120   BOOL InitMultipleMonitorStubs(void)
121   {
122     HMODULE hUser32;
123     static BOOL fInitDone;
124
125     if (fInitDone)
126     {
127       return g_pfnGetMonitorInfo != NULL;
128     }
129
130     if ((hUser32 = GetModuleHandle(TEXT("USER32"))) &&
131         (*(FARPROC*)&g_pfnGetSystemMetrics    = GetProcAddress(hUser32,"GetSystemMetrics")) &&
132         (*(FARPROC*)&g_pfnMonitorFromWindow   = GetProcAddress(hUser32,"MonitorFromWindow")) &&
133         (*(FARPROC*)&g_pfnMonitorFromRect     = GetProcAddress(hUser32,"MonitorFromRect")) &&
134         (*(FARPROC*)&g_pfnMonitorFromPoint    = GetProcAddress(hUser32,"MonitorFromPoint")) &&
135         (*(FARPROC*)&g_pfnEnumDisplayMonitors = GetProcAddress(hUser32,"EnumDisplayMonitors")) &&
136     #ifdef UNICODE
137         (*(FARPROC*)&g_pfnGetMonitorInfo      = GetProcAddress(hUser32,"GetMonitorInfoW")) &&
138         (*(FARPROC*)&g_pfnEnumDisplayDevices  = GetProcAddress(hUser32,"EnumDisplayDevicesW")) &&
139     #else
140         (*(FARPROC*)&g_pfnGetMonitorInfo      = GetProcAddress(hUser32,"GetMonitorInfoA")) &&
141         (*(FARPROC*)&g_pfnEnumDisplayDevices  = GetProcAddress(hUser32,"EnumDisplayDevicesA")) &&
142     #endif
143         (GetSystemMetrics(SM_CXVIRTUALSCREEN) >= GetSystemMetrics(SM_CXSCREEN)) &&
144         (GetSystemMetrics(SM_CYVIRTUALSCREEN) >= GetSystemMetrics(SM_CYSCREEN)) )
145     {
146       fInitDone = TRUE;
147       return TRUE;
148     }
149     else
150     {
151       g_pfnGetSystemMetrics    = NULL;
152       g_pfnMonitorFromWindow   = NULL;
153       g_pfnMonitorFromRect     = NULL;
154       g_pfnMonitorFromPoint    = NULL;
155       g_pfnGetMonitorInfo      = NULL;
156       g_pfnEnumDisplayMonitors = NULL;
157       g_pfnEnumDisplayDevices  = NULL;
158
159       fInitDone = TRUE;
160       return FALSE;
161     }
162   }
163
164   //---------------------------------------------------------------------------
165   //
166   // "stubbed" implementations of Monitor APIs that work with the primary           //  display
167   //
168   //---------------------------------------------------------------------------
169
170   int WINAPI
171   xGetSystemMetrics(int nIndex)
172   {
173     if (InitMultipleMonitorStubs())
174       return g_pfnGetSystemMetrics(nIndex);
175
176     switch (nIndex)
177     {
178     case SM_CMONITORS:
179     case SM_SAMEDISPLAYFORMAT:
180       return 1;
181
182     case SM_XVIRTUALSCREEN:
183     case SM_YVIRTUALSCREEN:
184       return 0;
185
186     case SM_CXVIRTUALSCREEN:
187       nIndex = SM_CXSCREEN;
188       break;
189
190     case SM_CYVIRTUALSCREEN:
191       nIndex = SM_CYSCREEN;
192       break;
193     }
194
195     return GetSystemMetrics(nIndex);
196   }
197
198   #define xPRIMARY_MONITOR ((HMONITOR)0x42)
199
200   HMONITOR WINAPI
201   xMonitorFromRect(LPCRECT lprcScreenCoords,
202                    UINT uFlags)
203   {
204     if (InitMultipleMonitorStubs())
205       return g_pfnMonitorFromRect(lprcScreenCoords, uFlags);
206
207     if ((uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
208         ((lprcScreenCoords->right > 0) &&
209         (lprcScreenCoords->bottom > 0) &&
210         (lprcScreenCoords->left < GetSystemMetrics(SM_CXSCREEN)) &&
211         (lprcScreenCoords->top < GetSystemMetrics(SM_CYSCREEN))))
212     {
213       return xPRIMARY_MONITOR;
214     }
215
216     return NULL;
217   }
218
219   HMONITOR WINAPI
220   xMonitorFromWindow(HWND hWnd,
221                      UINT uFlags)
222   {
223     RECT rc;
224
225     if (InitMultipleMonitorStubs())
226       return g_pfnMonitorFromWindow(hWnd, uFlags);
227
228     if (uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST))
229       return xPRIMARY_MONITOR;
230
231     if (GetWindowRect(hWnd, &rc))
232       return xMonitorFromRect(&rc, uFlags);
233
234     return NULL;
235   }
236
237   HMONITOR WINAPI
238   xMonitorFromPoint(POINT ptScreenCoords,
239                     UINT uFlags)
240   {
241     if (InitMultipleMonitorStubs())
242       return g_pfnMonitorFromPoint(ptScreenCoords, uFlags);
243
244     if ((uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
245         ((ptScreenCoords.x >= 0) &&
246         (ptScreenCoords.x < GetSystemMetrics(SM_CXSCREEN)) &&
247         (ptScreenCoords.y >= 0) &&
248         (ptScreenCoords.y < GetSystemMetrics(SM_CYSCREEN))))
249     {
250       return xPRIMARY_MONITOR;
251     }
252
253     return NULL;
254   }
255
256   BOOL WINAPI
257   xGetMonitorInfo(HMONITOR hMonitor,
258                   LPMONITORINFO lpMonitorInfo)
259   {
260     RECT rcWork;
261
262     if (InitMultipleMonitorStubs())
263       return g_pfnGetMonitorInfo(hMonitor, lpMonitorInfo);
264
265     if ((hMonitor == xPRIMARY_MONITOR) && lpMonitorInfo &&
266         (lpMonitorInfo->cbSize >= sizeof(MONITORINFO)) &&
267         SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0))
268     {
269       lpMonitorInfo->rcMonitor.left = 0;
270       lpMonitorInfo->rcMonitor.top  = 0;
271       lpMonitorInfo->rcMonitor.right  = GetSystemMetrics(SM_CXSCREEN);
272       lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics(SM_CYSCREEN);
273       lpMonitorInfo->rcWork = rcWork;
274       lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
275
276       if (lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX))
277           lstrcpy(((MONITORINFOEX*)lpMonitorInfo)->szDevice,
278           TEXT("DISPLAY"));
279
280       return TRUE;
281     }
282
283     return FALSE;
284   }
285
286   BOOL WINAPI
287   xEnumDisplayMonitors(HDC hdc,
288                        LPCRECT lprcIntersect, 
289                        MONITORENUMPROC lpfnEnumProc,
290                        LPARAM lData)
291   {
292     RECT rcCallback, rcLimit;
293
294     if (InitMultipleMonitorStubs())
295       return g_pfnEnumDisplayMonitors(hdc, lprcIntersect, lpfnEnumProc, lData);
296     
297     if (!lpfnEnumProc)
298       return FALSE;
299
300     rcLimit.left   = 0;
301     rcLimit.top    = 0;
302     rcLimit.right  = GetSystemMetrics(SM_CXSCREEN);
303     rcLimit.bottom = GetSystemMetrics(SM_CYSCREEN);
304
305     if (hdc)
306     {
307       RECT rcClip;
308       HWND hWnd;
309
310       if ((hWnd = WindowFromDC(hdc)) == NULL)
311         return FALSE;
312
313       switch (GetClipBox(hdc, &rcClip))
314       {
315       default:
316         MapWindowPoints(NULL, hWnd, (LPPOINT)&rcLimit, 2);
317         if (IntersectRect(&rcCallback, &rcClip, &rcLimit))
318           break;
319       //fall thru
320       case NULLREGION:
321         return TRUE;
322       case ERROR:
323         return FALSE;
324       }
325
326       rcLimit = rcCallback;
327     }
328
329     if (!lprcIntersect || IntersectRect(&rcCallback, lprcIntersect, &rcLimit))
330     {
331       lpfnEnumProc(xPRIMARY_MONITOR, hdc, &rcCallback, lData);
332     }
333
334     return TRUE;
335   }
336
337   BOOL WINAPI
338   xEnumDisplayDevices(LPVOID lpReserved,
339                       int iDeviceNum, 
340                       DISPLAY_DEVICE * pDisplayDevice,
341                       DWORD dwFlags)
342   {
343     if (InitMultipleMonitorStubs())
344       return g_pfnEnumDisplayDevices(lpReserved, iDeviceNum, pDisplayDevice, dwFlags);
345     
346     return FALSE;
347   }
348
349   #undef xPRIMARY_MONITOR
350   #undef COMPILE_MULTIMON_STUBS
351
352 #else    // COMPILE_MULTIMON_STUBS
353
354   extern int      WINAPI xGetSystemMetrics(int);
355   extern HMONITOR WINAPI xMonitorFromWindow(HWND, UINT);
356   extern HMONITOR WINAPI xMonitorFromRect(LPCRECT, UINT);
357   extern HMONITOR WINAPI xMonitorFromPoint(POINT, UINT);
358   extern BOOL     WINAPI xGetMonitorInfo(HMONITOR, LPMONITORINFO);
359   extern BOOL     WINAPI xEnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
360   extern BOOL     WINAPI xEnumDisplayDevices(LPVOID, int, DISPLAY_DEVICE *, DWORD);
361
362 #endif    // COMPILE_MULTIMON_STUBS
363
364 //
365 // build defines that replace the regular APIs with our versions
366 //
367 #define GetSystemMetrics    xGetSystemMetrics
368 #define MonitorFromWindow   xMonitorFromWindow
369 #define MonitorFromRect     xMonitorFromRect
370 #define MonitorFromPoint    xMonitorFromPoint
371 #define GetMonitorInfo      xGetMonitorInfo
372 #define EnumDisplayMonitors xEnumDisplayMonitors
373 #define EnumDisplayDevices  xEnumDisplayDevices
374
375 #ifdef __cplusplus
376 }
377 #endif // __cplusplus
378
379 #endif // WIN32
380
381 #endif // __MULTIMON_H