source: trunk/src/user32/win32wbasepos.cpp@ 1376

Last change on this file since 1376 was 1376, checked in by sandervl, 26 years ago

position change bugfixes

File size: 14.9 KB
Line 
1/* $Id: win32wbasepos.cpp,v 1.4 1999-10-20 13:46:28 sandervl Exp $ */
2/*
3 * Win32 Window Base Class for OS/2 (nonclient/position methods)
4 *
5 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999 Daniela Engert (dani@ngrt.de)
7 *
8 * Parts based on Wine Windows code (windows\win.c, windows\nonclient.c)
9 *
10 * Copyright 1993, 1994 Alexandre Julliard
11 *
12 * TODO: Not thread/process safe
13 *
14 * Wine code based on build 990815
15 *
16 * Project Odin Software License can be found in LICENSE.TXT
17 *
18 */
19#include <os2win.h>
20#include <win.h>
21#include <stdlib.h>
22#include <string.h>
23#include <stdarg.h>
24#include <assert.h>
25#include <misc.h>
26#include <heapstring.h>
27#include <win32wbase.h>
28#include <winres.h>
29#include <spy.h>
30#include "wndmsg.h"
31#include "hooks.h"
32#include "oslibwin.h"
33#include "oslibutil.h"
34#include "oslibgdi.h"
35#include "oslibres.h"
36#include "oslibmenu.h"
37#include "oslibdos.h"
38#include "syscolor.h"
39#include "win32wndhandle.h"
40#include "heapshared.h"
41#include "dc.h"
42#include "pmframe.h"
43#include "win32wdesktop.h"
44
45 /* Some useful macros */
46#define HAS_DLGFRAME(style,exStyle) \
47 (((exStyle) & WS_EX_DLGMODALFRAME) || \
48 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
49
50#define HAS_THICKFRAME(style,exStyle) \
51 (((style) & WS_THICKFRAME) && \
52 !((exStyle) & WS_EX_DLGMODALFRAME))
53
54#define HAS_THINFRAME(style) \
55 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
56
57#define HAS_BIGFRAME(style,exStyle) \
58 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
59 ((exStyle) & WS_EX_DLGMODALFRAME))
60
61#define HAS_ANYFRAME(style,exStyle) \
62 (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
63 ((exStyle) & WS_EX_DLGMODALFRAME) || \
64 !((style) & (WS_CHILD | WS_POPUP)))
65
66#define HAS_3DFRAME(exStyle) \
67 ((exStyle & WS_EX_CLIENTEDGE) || (exStyle & WS_EX_STATICEDGE) || (exStyle & WS_EX_WINDOWEDGE))
68
69#define HAS_BORDER(style, exStyle) \
70 ((style & WS_BORDER) || HAS_THICKFRAME(style) || HAS_DLGFRAME(style,exStyle))
71
72#define IS_OVERLAPPED(style) \
73 !(style & (WS_CHILD | WS_POPUP))
74
75#define HAS_MENU() (!(getStyle() & WS_CHILD) && (GetMenu() != 0))
76
77#if 0
78/***********************************************************************
79 * WINPOS_MinMaximize
80 *
81 * Fill in lpRect and return additional flags to be used with SetWindowPos().
82 * This function assumes that 'cmd' is different from the current window
83 * state.
84 */
85UINT Win32BaseWindow::MinMaximize(UINT cmd, LPRECT lpRect )
86{
87 UINT swpFlags = 0;
88 POINT pt, size;
89 LPINTERNALPOS lpPos;
90
91 size.x = rectWindow.left; size.y = rectWindow.top;
92 lpPos = WINPOS_InitInternalPos( wndPtr, size, &rectWindow );
93
94 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, hwndSelf, cmd))
95 {
96 if( dwStyle & WS_MINIMIZE )
97 {
98 if( !SendMessageA(WM_QUERYOPEN, 0, 0L ) )
99 return (SWP_NOSIZE | SWP_NOMOVE);
100 swpFlags |= SWP_NOCOPYBITS;
101 }
102 switch( cmd )
103 {
104 case SW_MINIMIZE:
105 if( dwStyle & WS_MAXIMIZE)
106 {
107 flags |= WIN_RESTORE_MAX;
108 dwStyle &= ~WS_MAXIMIZE;
109 }
110 else
111 flags &= ~WIN_RESTORE_MAX;
112 dwStyle |= WS_MINIMIZE;
113
114#if 0
115 if( flags & WIN_NATIVE )
116 if( pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
117 swpFlags |= MINMAX_NOSWP;
118#endif
119
120 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
121
122 SetRect(lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
123 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
124 swpFlags |= SWP_NOCOPYBITS;
125 break;
126
127 case SW_MAXIMIZE:
128 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
129
130 if( dwStyle & WS_MINIMIZE )
131 {
132 if( flags & WIN_NATIVE )
133 if( pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
134 swpFlags |= MINMAX_NOSWP;
135
136 WINPOS_ShowIconTitle( wndPtr, FALSE );
137 dwStyle &= ~WS_MINIMIZE;
138 }
139 dwStyle |= WS_MAXIMIZE;
140
141 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
142 size.x, size.y );
143 break;
144
145 case SW_RESTORE:
146 if( dwStyle & WS_MINIMIZE )
147 {
148 if( flags & WIN_NATIVE )
149 if( pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
150 swpFlags |= MINMAX_NOSWP;
151
152 dwStyle &= ~WS_MINIMIZE;
153 WINPOS_ShowIconTitle( wndPtr, FALSE );
154
155 if( flags & WIN_RESTORE_MAX)
156 {
157 /* Restore to maximized position */
158 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
159 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
160 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
161 dwStyle |= WS_MAXIMIZE;
162 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
163 break;
164 }
165 }
166 else
167 if( !(dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
168 else dwStyle &= ~WS_MAXIMIZE;
169
170 /* Restore to normal position */
171
172 *lpRect = lpPos->rectNormal;
173 lpRect->right -= lpRect->left;
174 lpRect->bottom -= lpRect->top;
175
176 break;
177 }
178 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
179 return swpFlags;
180}
181#endif
182/*******************************************************************
183 * GetMinMaxInfo
184 *
185 * Get the minimized and maximized information for a window.
186 */
187void Win32BaseWindow::GetMinMaxInfo(POINT *maxSize, POINT *maxPos,
188 POINT *minTrack, POINT *maxTrack )
189{
190 MINMAXINFO MinMax;
191 INT xinc, yinc;
192
193 /* Compute default values */
194
195 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
196 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
197 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
198 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
199 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
200 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
201
202 if (flags & WIN_MANAGED) xinc = yinc = 0;
203 else if (HAS_DLGFRAME( dwStyle, dwExStyle ))
204 {
205 xinc = GetSystemMetrics(SM_CXDLGFRAME);
206 yinc = GetSystemMetrics(SM_CYDLGFRAME);
207 }
208 else
209 {
210 xinc = yinc = 0;
211 if (HAS_THICKFRAME(dwStyle, dwExStyle))
212 {
213 xinc += GetSystemMetrics(SM_CXFRAME);
214 yinc += GetSystemMetrics(SM_CYFRAME);
215 }
216 if (dwStyle & WS_BORDER)
217 {
218 xinc += GetSystemMetrics(SM_CXBORDER);
219 yinc += GetSystemMetrics(SM_CYBORDER);
220 }
221 }
222 MinMax.ptMaxSize.x += 2 * xinc;
223 MinMax.ptMaxSize.y += 2 * yinc;
224
225#if 0
226 lpPos = (LPINTERNALPOS)GetPropA( hwndSelf, atomInternalPos );
227 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
228 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
229 else
230 {
231#endif
232 MinMax.ptMaxPosition.x = -xinc;
233 MinMax.ptMaxPosition.y = -yinc;
234// }
235
236 SendMessageA(WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
237
238 /* Some sanity checks */
239
240 dprintf(("GetMinMaxInfo: %ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
241 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
242 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
243 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
244 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y));
245 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
246 MinMax.ptMinTrackSize.x );
247 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
248 MinMax.ptMinTrackSize.y );
249
250 if (maxSize) *maxSize = MinMax.ptMaxSize;
251 if (maxPos) *maxPos = MinMax.ptMaxPosition;
252 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
253 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
254}
255/***********************************************************************
256 * WINPOS_SendNCCalcSize
257 *
258 * Send a WM_NCCALCSIZE message to a window.
259 * All parameters are read-only except newClientRect.
260 * oldWindowRect, oldClientRect and winpos must be non-NULL only
261 * when calcValidRect is TRUE.
262 */
263LONG Win32BaseWindow::SendNCCalcSize(BOOL calcValidRect, RECT *newWindowRect,
264 RECT *oldWindowRect,
265 RECT *oldClientRect, WINDOWPOS *winpos,
266 RECT *newClientRect )
267{
268 NCCALCSIZE_PARAMS params;
269 WINDOWPOS winposCopy;
270 LONG result;
271
272 params.rgrc[0] = *newWindowRect;
273 if (calcValidRect)
274 {
275 winposCopy = *winpos;
276 params.rgrc[1] = *oldWindowRect;
277 params.rgrc[2] = *oldClientRect;
278 params.lppos = &winposCopy;
279 }
280 result = SendMessageA(WM_NCCALCSIZE, calcValidRect,
281 (LPARAM)&params );
282 *newClientRect = params.rgrc[0];
283 return result;
284}
285//******************************************************************************
286//******************************************************************************
287LONG Win32BaseWindow::NCHandleCalcSize(WPARAM wParam, NCCALCSIZE_PARAMS *ncsize)
288{
289 LONG result = 0;
290
291 if (getStyle() & CS_VREDRAW) result |= WVR_VREDRAW;
292 if (getStyle() & CS_HREDRAW) result |= WVR_HREDRAW;
293
294//TODO: Wine calculates new size of client area even when window is iconic (client edges)
295 if(!(getStyle() & (WS_MINIMIZE | WS_ICONIC)))
296 {
297 dprintf(("NCHandleCalcSize %x (%d,%d) (%d,%d)", getWindowHandle(), ncsize->rgrc[0].left, ncsize->rgrc[0].top, ncsize->rgrc[0].right, ncsize->rgrc[0].bottom));
298 OSLibWinCalcFrameRect(getOS2FrameWindowHandle(), &ncsize->rgrc[0], TRUE); //frame -> client
299 dprintf(("NCHandleCalcSize Adjusted client rect (%d,%d) (%d,%d)", ncsize->rgrc[0].left, ncsize->rgrc[0].top, ncsize->rgrc[0].right, ncsize->rgrc[0].bottom));
300
301 OffsetRect(&ncsize->rgrc[0], -ncsize->rgrc[0].left, -ncsize->rgrc[0].top);
302 }
303#if 0
304//TODO: Docs say app should return 0 when fCalcValidRects == 0; Wine doesn't do this
305 if(wParam == 0) //fCalcValidRects
306 return 0;
307#endif
308 return result;
309}
310/***********************************************************************
311 * WIN_WindowNeedsWMBorder
312 *
313 * This method defines the rules for a window to have a WM border,
314 * caption... It is used for consitency purposes.
315 */
316BOOL Win32BaseWindow::WindowNeedsWMBorder( DWORD style, DWORD exStyle )
317{
318// if (!(style & WS_CHILD) && Options.managed &&
319 if (!(style & WS_CHILD) &&
320 (((style & WS_CAPTION) == WS_CAPTION) ||
321 (style & WS_THICKFRAME)))
322 return TRUE;
323 return FALSE;
324}
325/******************************************************************************
326 * NC_AdjustRectOuter95
327 *
328 * Computes the size of the "outside" parts of the window based on the
329 * parameters of the client area.
330 *
331 + PARAMS
332 * LPRECT16 rect
333 * DWORD style
334 * BOOL32 menu
335 * DWORD exStyle
336 *
337 * NOTES
338 * "Outer" parts of a window means the whole window frame, caption and
339 * menu bar. It does not include "inner" parts of the frame like client
340 * edge, static edge or scroll bars.
341 *
342 * Revision history
343 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
344 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
345 *
346 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
347 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
348 * NC_AdjustRectInner95 and added handling of Win95 styles.
349 *
350 * 28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
351 * Streamlined window style checks.
352 *
353 *****************************************************************************/
354void Win32BaseWindow::NC_AdjustRectOuter(LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
355{
356 if(style & WS_ICONIC) return;
357
358 /* Decide if the window will be managed (see CreateWindowEx) */
359// if (!WindowNeedsWMBorder(style, exStyle))
360// {
361 if (HAS_THICKFRAME( style, exStyle ))
362 InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
363 else
364 if (HAS_DLGFRAME( style, exStyle ))
365 InflateRect(rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
366 else
367 if (HAS_THINFRAME( style ))
368 InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
369
370 if ((style & WS_CAPTION) == WS_CAPTION)
371 {
372 if (exStyle & WS_EX_TOOLWINDOW)
373 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
374 else
375 rect->top -= GetSystemMetrics(SM_CYCAPTION);
376 }
377// }
378
379 if (menu)
380 rect->top -= GetSystemMetrics(SM_CYMENU);
381}
382/******************************************************************************
383 * NC_AdjustRectInner95
384 *
385 * Computes the size of the "inside" part of the window based on the
386 * parameters of the client area.
387 *
388 + PARAMS
389 * LPRECT16 rect
390 * DWORD style
391 * DWORD exStyle
392 *
393 * NOTES
394 * "Inner" part of a window means the window frame inside of the flat
395 * window frame. It includes the client edge, the static edge and the
396 * scroll bars.
397 *
398 * Revision history
399 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
400 * Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
401 *
402 * 20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
403 * Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
404 * NC_AdjustRectInner95 and added handling of Win95 styles.
405 *
406 *****************************************************************************/
407void Win32BaseWindow::NC_AdjustRectInner(LPRECT rect, DWORD style, DWORD exStyle)
408{
409 if(style & WS_ICONIC) return;
410
411 if (exStyle & WS_EX_CLIENTEDGE)
412 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
413
414 if (exStyle & WS_EX_STATICEDGE)
415 InflateRect(rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
416
417 if (style & WS_VSCROLL) rect->right += GetSystemMetrics(SM_CXVSCROLL);
418 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
419}
420/***********************************************************************
421 * WINPOS_HandleWindowPosChanging16
422 *
423 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
424 */
425LONG Win32BaseWindow::HandleWindowPosChanging(WINDOWPOS *winpos)
426{
427 POINT maxSize, minTrack;
428
429 if (winpos->flags & SWP_NOSIZE)
430 return 1;
431
432 if ((getStyle() & WS_THICKFRAME) ||
433 ((getStyle() & (WS_POPUP | WS_CHILD)) == 0))
434 {
435 GetMinMaxInfo(&maxSize, NULL, &minTrack, NULL );
436 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
437 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
438 if (!(getStyle() & WS_MINIMIZE))
439 {
440 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
441 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
442 }
443 return 0;
444 }
445 return 1;
446}
447//******************************************************************************
448//******************************************************************************
449
Note: See TracBrowser for help on using the repository browser.