Implementation of the new monitor abstraction.
[wine] / windows / multimon.c
1 /*
2  * Multimonitor APIs
3  *
4  * Copyright 1998 Turchanov Sergey
5  */
6
7 #include "monitor.h"
8 #include "windows.h"
9
10 /**********************************************************************/
11
12 #define xPRIMARY_MONITOR ((HMONITOR)0x12340042)
13
14 MONITOR MONITOR_PrimaryMonitor;
15
16 /***********************************************************************
17  *              MONITOR_Initialize
18  */
19 void MONITOR_Initialize(MONITOR *pMonitor)
20 {
21   pMonitor->pDriver->pInitialize(pMonitor);
22 }
23
24 /***********************************************************************
25  *              MONITOR_Finalize
26  */
27 void MONITOR_Finalize(MONITOR *pMonitor)
28 {
29   pMonitor->pDriver->pFinalize(pMonitor);
30 }
31
32 /***********************************************************************
33  *              MONITOR_GetWidth
34  */
35 int MONITOR_GetWidth(MONITOR *pMonitor)
36 {
37   return pMonitor->pDriver->pGetWidth(pMonitor);
38 }
39
40 /***********************************************************************
41  *              MONITOR_GetHeight
42  */
43 int MONITOR_GetHeight(MONITOR *pMonitor)
44 {
45   return pMonitor->pDriver->pGetHeight(pMonitor);
46 }
47
48 /***********************************************************************
49  *              MONITOR_GetDepth
50  */
51 int MONITOR_GetDepth(MONITOR *pMonitor)
52 {
53   return pMonitor->pDriver->pGetDepth(pMonitor);
54 }
55
56 /**********************************************************************/
57
58 HMONITOR WINAPI MonitorFromPoint(POINT32 ptScreenCoords, DWORD dwFlags)
59 {
60     if ((dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
61         ((ptScreenCoords.x >= 0) &&
62         (ptScreenCoords.x < GetSystemMetrics32(SM_CXSCREEN)) &&
63         (ptScreenCoords.y >= 0) &&
64         (ptScreenCoords.y < GetSystemMetrics32(SM_CYSCREEN))))
65     {
66         return xPRIMARY_MONITOR;
67     }
68         return NULL;
69 }
70
71 HMONITOR WINAPI MonitorFromRect(LPRECT32 lprcScreenCoords, DWORD dwFlags)
72 {
73     if ((dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
74         ((lprcScreenCoords->right > 0) &&
75         (lprcScreenCoords->bottom > 0) &&
76         (lprcScreenCoords->left < GetSystemMetrics32(SM_CXSCREEN)) &&
77         (lprcScreenCoords->top < GetSystemMetrics32(SM_CYSCREEN))))
78     {
79         return xPRIMARY_MONITOR;
80     }
81     return NULL;
82 }
83
84 HMONITOR WINAPI MonitorFromWindow(HWND32 hWnd, DWORD dwFlags)
85 {
86     WINDOWPLACEMENT32 wp;
87
88     if (dwFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST))
89         return xPRIMARY_MONITOR;
90
91     if (IsIconic32(hWnd) ? 
92             GetWindowPlacement32(hWnd, &wp) : 
93             GetWindowRect32(hWnd, &wp.rcNormalPosition)) {
94
95         return MonitorFromRect(&wp.rcNormalPosition, dwFlags);
96     }
97
98     return NULL;
99 }
100
101 BOOL32 WINAPI GetMonitorInfo32A(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)
102 {
103     RECT32 rcWork;
104
105     if ((hMonitor == xPRIMARY_MONITOR) &&
106         lpMonitorInfo &&
107         (lpMonitorInfo->cbSize >= sizeof(MONITORINFO)) &&
108         SystemParametersInfo32A(SPI_GETWORKAREA, 0, &rcWork, 0))
109     {
110         lpMonitorInfo->rcMonitor.left = 0;
111         lpMonitorInfo->rcMonitor.top  = 0;
112         lpMonitorInfo->rcMonitor.right  = GetSystemMetrics32(SM_CXSCREEN);
113         lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics32(SM_CYSCREEN);
114         lpMonitorInfo->rcWork = rcWork;
115         lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
116         
117         if (lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX32A))
118             lstrcpy32A(((MONITORINFOEX32A*)lpMonitorInfo)->szDevice, "DISPLAY");
119
120         return TRUE;
121     }
122
123     return FALSE;
124 }
125
126 BOOL32 WINAPI GetMonitorInfo32W(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)
127 {
128     RECT32 rcWork;
129
130     if ((hMonitor == xPRIMARY_MONITOR) &&
131         lpMonitorInfo &&
132         (lpMonitorInfo->cbSize >= sizeof(MONITORINFO)) &&
133         SystemParametersInfo32W(SPI_GETWORKAREA, 0, &rcWork, 0))
134     {
135         lpMonitorInfo->rcMonitor.left = 0;
136         lpMonitorInfo->rcMonitor.top  = 0;
137         lpMonitorInfo->rcMonitor.right  = GetSystemMetrics32(SM_CXSCREEN);
138         lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics32(SM_CYSCREEN);
139         lpMonitorInfo->rcWork = rcWork;
140         lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
141
142         if (lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX32W))
143             lstrcpy32W(((MONITORINFOEX32W*)lpMonitorInfo)->szDevice, (LPCWSTR)"D\0I\0S\0P\0L\0A\0Y\0\0");
144
145         return TRUE;
146     }
147
148     return FALSE;
149 }
150
151 BOOL32 WINAPI EnumDisplayMonitors(
152         HDC32             hdcOptionalForPainting,
153         LPRECT32         lprcEnumMonitorsThatIntersect,
154         MONITORENUMPROC lpfnEnumProc,
155         LPARAM          dwData)
156 {
157     RECT32 rcLimit;
158
159     if (!lpfnEnumProc)
160         return FALSE;
161
162     rcLimit.left   = 0;
163     rcLimit.top    = 0;
164     rcLimit.right  = GetSystemMetrics32(SM_CXSCREEN);
165     rcLimit.bottom = GetSystemMetrics32(SM_CYSCREEN);
166
167     if (hdcOptionalForPainting)
168     {
169         RECT32    rcClip;
170         POINT32   ptOrg;
171
172         switch (GetClipBox32(hdcOptionalForPainting, &rcClip))
173         {
174         default:
175             if (!GetDCOrgEx(hdcOptionalForPainting, &ptOrg))
176                 return FALSE;
177
178             OffsetRect32(&rcLimit, -ptOrg.x, -ptOrg.y);
179             if (IntersectRect32(&rcLimit, &rcLimit, &rcClip) &&
180                 (!lprcEnumMonitorsThatIntersect ||
181                      IntersectRect32(&rcLimit, &rcLimit, lprcEnumMonitorsThatIntersect))) {
182
183                 break;
184             }
185             /*fall thru */
186         case NULLREGION:
187              return TRUE;
188         case ERROR:
189              return FALSE;
190         }
191     } else {
192         if (    lprcEnumMonitorsThatIntersect &&
193                 !IntersectRect32(&rcLimit, &rcLimit, lprcEnumMonitorsThatIntersect)) {
194
195             return TRUE;
196         }
197     }
198
199     return lpfnEnumProc(
200             xPRIMARY_MONITOR,
201             hdcOptionalForPainting,
202             &rcLimit,
203             dwData);
204 }