[Win32SS] Fix maximized window positioning.
[reactos.git] / win32ss / user / user32 / windows / winpos.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS user32.dll
4 * FILE: win32ss/user/user32/windows/winpos.c
5 * PURPOSE: Window management
6 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * UPDATE HISTORY:
8 * 06-06-2001 CSH Created
9 */
10
11 #include <user32.h>
12
13 WINE_DEFAULT_DEBUG_CHANNEL(user32);
14
15 void mirror_rect( const RECT *window_rect, RECT *rect )
16 {
17 int width = window_rect->right - window_rect->left;
18 int tmp = rect->left;
19 rect->left = width - rect->right;
20 rect->right = width - tmp;
21 }
22
23 /* FUNCTIONS *****************************************************************/
24
25 #if 0 // Keep legacy code. Moved to Win32k:NtUser:WinPos.c.
26 #define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
27
28 UINT WINAPI
29 WinPosGetMinMaxInfo(HWND hwnd, POINT* maxSize, POINT* maxPos,
30 POINT* minTrack, POINT* maxTrack)
31 {
32 MINMAXINFO MinMax;
33 HMONITOR monitor;
34 INT xinc, yinc;
35 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
36 LONG adjustedStyle;
37 LONG exstyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
38 RECT rc;
39 WND *win;
40
41 /* Compute default values */
42
43 GetWindowRect(hwnd, &rc);
44 MinMax.ptReserved.x = rc.left;
45 MinMax.ptReserved.y = rc.top;
46
47 if ((style & WS_CAPTION) == WS_CAPTION)
48 adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
49 else
50 adjustedStyle = style;
51
52 GetClientRect(GetAncestor(hwnd,GA_PARENT), &rc);
53 AdjustWindowRectEx(&rc, adjustedStyle, ((style & WS_POPUP) && GetMenu(hwnd)), exstyle);
54
55 xinc = -rc.left;
56 yinc = -rc.top;
57
58 MinMax.ptMaxSize.x = rc.right - rc.left;
59 MinMax.ptMaxSize.y = rc.bottom - rc.top;
60 if (style & (WS_DLGFRAME | WS_BORDER))
61 {
62 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
63 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
64 }
65 else
66 {
67 MinMax.ptMinTrackSize.x = 2 * xinc;
68 MinMax.ptMinTrackSize.y = 2 * yinc;
69 }
70 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXMAXTRACK);
71 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYMAXTRACK);
72 MinMax.ptMaxPosition.x = -xinc;
73 MinMax.ptMaxPosition.y = -yinc;
74
75 if ((win = ValidateHwnd( hwnd )) )//&& win != WND_DESKTOP && win != WND_OTHER_PROCESS)
76 {
77 if (!EMPTYPOINT(win->InternalPos.MaxPos)) MinMax.ptMaxPosition = win->InternalPos.MaxPos;
78 }
79
80 SendMessageW( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
81
82 /* if the app didn't change the values, adapt them for the current monitor */
83
84 if ((monitor = MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY )))
85 {
86 RECT rc_work;
87 MONITORINFO mon_info;
88
89 mon_info.cbSize = sizeof(mon_info);
90 GetMonitorInfoW( monitor, &mon_info );
91
92 rc_work = mon_info.rcMonitor;
93
94 if (style & WS_MAXIMIZEBOX)
95 {
96 if ((style & WS_CAPTION) == WS_CAPTION || !(style & (WS_CHILD | WS_POPUP)))
97 rc_work = mon_info.rcWork;
98 }
99
100 if (MinMax.ptMaxSize.x == GetSystemMetrics(SM_CXSCREEN) + 2 * xinc &&
101 MinMax.ptMaxSize.y == GetSystemMetrics(SM_CYSCREEN) + 2 * yinc)
102 {
103 MinMax.ptMaxSize.x = (rc_work.right - rc_work.left) + 2 * xinc;
104 MinMax.ptMaxSize.y = (rc_work.bottom - rc_work.top) + 2 * yinc;
105 }
106 if (MinMax.ptMaxPosition.x == -xinc && MinMax.ptMaxPosition.y == -yinc)
107 {
108 MinMax.ptMaxPosition.x = rc_work.left - xinc;
109 MinMax.ptMaxPosition.y = rc_work.top - yinc;
110 }
111 }
112
113 /* Some sanity checks */
114
115 TRACE("%d %d / %d %d / %d %d / %d %d\n",
116 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
117 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
118 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
119 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
120 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
121 MinMax.ptMinTrackSize.x );
122 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
123 MinMax.ptMinTrackSize.y );
124
125 if (maxSize) *maxSize = MinMax.ptMaxSize;
126 if (maxPos) *maxPos = MinMax.ptMaxPosition;
127 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
128 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
129
130 return 0; //FIXME: what does it return? Wine returns MINMAXINFO.
131 }
132 #endif
133
134 /*
135 * @implemented
136 */
137 HWND WINAPI
138 GetActiveWindow(VOID)
139 {
140 return (HWND)NtUserGetThreadState(THREADSTATE_ACTIVEWINDOW);
141 }
142
143
144 /*
145 * @unimplemented
146 */
147 UINT WINAPI
148 ArrangeIconicWindows(HWND hWnd)
149 {
150 return NtUserxArrangeIconicWindows( hWnd );
151 }
152
153 /*
154 * @implemented
155 */
156 HWND WINAPI
157 WindowFromPoint(POINT Point)
158 {
159 //TODO: Determine what the actual parameters to
160 // NtUserWindowFromPoint are.
161 return NtUserWindowFromPoint(Point.x, Point.y);
162 }
163
164 /*
165 * @implemented
166 */
167 int WINAPI
168 MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints)
169 {
170 PWND FromWnd = NULL, ToWnd = NULL;
171 BOOL mirror_from, mirror_to;
172 POINT Delta;
173 UINT i;
174 int Change = 1;
175
176 if (hWndFrom)
177 {
178 FromWnd = ValidateHwnd(hWndFrom);
179 if (!FromWnd)
180 return 0;
181 }
182 if (hWndTo)
183 {
184 ToWnd = ValidateHwnd(hWndTo);
185 if (!ToWnd)
186 return 0;
187 }
188
189 /* Note: Desktop Top and Left is always 0! */
190 Delta.x = Delta.y = 0;
191 mirror_from = mirror_to = FALSE;
192
193 if (FromWnd && hWndFrom != GetDesktopWindow()) // FromWnd->fnid != FNID_DESKTOP)
194 {
195 if (FromWnd->ExStyle & WS_EX_LAYOUTRTL)
196 {
197 mirror_from = TRUE;
198 Change = -Change;
199 Delta.x = -FromWnd->rcClient.right;
200 }
201 else
202 Delta.x = FromWnd->rcClient.left;
203 Delta.y = FromWnd->rcClient.top;
204 }
205
206 if (ToWnd && hWndTo != GetDesktopWindow()) // ToWnd->fnid != FNID_DESKTOP)
207 {
208 if (ToWnd->ExStyle & WS_EX_LAYOUTRTL)
209 {
210 mirror_to = TRUE;
211 Change = -Change;
212 Delta.x += Change * ToWnd->rcClient.right;
213 }
214 else
215 Delta.x -= Change * ToWnd->rcClient.left;
216 Delta.y -= ToWnd->rcClient.top;
217 }
218
219 for (i = 0; i != cPoints; i++)
220 {
221 lpPoints[i].x += Delta.x;
222 lpPoints[i].x *= Change;
223 lpPoints[i].y += Delta.y;
224 }
225
226 if ((mirror_from || mirror_to) && cPoints == 2) /* special case for rectangle */
227 {
228 int tmp = min(lpPoints[0].x, lpPoints[1].x);
229 lpPoints[1].x = max(lpPoints[0].x, lpPoints[1].x);
230 lpPoints[0].x = tmp;
231 }
232
233 return MAKELONG(LOWORD(Delta.x), LOWORD(Delta.y));
234 }
235
236 /*
237 * @implemented
238 */
239 BOOL WINAPI
240 ScreenToClient(HWND hWnd, LPPOINT lpPoint)
241 {
242 PWND Wnd;
243 /* Note: Desktop Top and Left is always 0! */
244 Wnd = ValidateHwnd(hWnd);
245 if (!Wnd)
246 return FALSE;
247
248 if (hWnd != GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
249 {
250 if (Wnd->ExStyle & WS_EX_LAYOUTRTL)
251 lpPoint->x = Wnd->rcClient.right - lpPoint->x;
252 else
253 lpPoint->x -= Wnd->rcClient.left;
254 lpPoint->y -= Wnd->rcClient.top;
255 }
256 return TRUE;
257 }
258
259 /*
260 * @implemented
261 */
262 BOOL WINAPI
263 ClientToScreen(HWND hWnd, LPPOINT lpPoint)
264 {
265 PWND Wnd;
266 /* Note: Desktop Top and Left is always 0! */
267 Wnd = ValidateHwnd(hWnd);
268 if (!Wnd)
269 return FALSE;
270
271 if ( hWnd != GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
272 {
273 if (Wnd->ExStyle & WS_EX_LAYOUTRTL)
274 lpPoint->x = Wnd->rcClient.right - lpPoint->x;
275 else
276 lpPoint->x += Wnd->rcClient.left;
277 lpPoint->y += Wnd->rcClient.top;
278 }
279 return TRUE;
280 }